Type coercion in Perl6 - raku

If I have an an object of type Str, and I want to coerce it into an Int, it is my understanding that I can do this by calling the method Int on the Str-object, like so:
"100".Int
I (think I) know I can do this because the Str-type documentation at https://docs.perl6.org/type/Str lists the Int-method. Now, to coerce this newly created Int into an object of type Complex, I tried the following coercion:
"100".Int.Complex
which works :-) So no problem. Except that I can't figure out why it works. The Int-type documentation at https://docs.perl6.org/type/Int does not list a method Complex. I did find a method with this name for the class ComplexStr, but I have no clue if this is somehow relevant to my Int, or not.
So the question is: how does the above coercion work? Where does the method Complex come from? And how could I have known I can actually call it on an Int-object before trying?

This is merely a case of incomplete documentation.
You can always find out what methods an object supports by calling .^methods on it:
perl6 -e '$_>>.name.join(", ").say for 123.^methods.sort(*.name).rotor(5 => 0, :partial)'
ACCEPTS, Bool, Bridge, Capture, Complex
DUMP, FatRat, Int, Num, Numeric
Range, Rat, Real, Str, WHICH
abs, acos, acosec, acosech, acosh
acotan, acotanh, asec, asech, asin
asinh, atan, atan2, atanh, base
ceiling, chr, cis, conj, cos
cosec, cosech, cosh, cotan, cotanh
exp, expmod, floor, gist, is-prime
isNaN, log, log10, lsb, msb
narrow, new, perl, polymod, pred
rand, roots, round, sec, sech
sign, sin, sinh, sqrt, succ
In the mean time, I pushed a commit to the docs repo that adds the missing method. The website is already regenerated with the change: https://docs.perl6.org/type/Int#(Real)_method_Complex

(This is more an extended comment than an answer. I know only Perl 5.)
From https://docs.perl6.org/type/Cool:
Methods in Cool coerce the invocant to a more specific type, and then
call the same method on that type. For example both Int and Str
inherit from Cool, and calling method substr on an Int converts the
integer to Str first.
123.substr(1, 1); # '2', same as 123.Str.substr(1, 1)
So it seems that 123.substr(1, 1) is like Cool(123).substr(1, 1) in a more traditional notation, which is then rewritten to Str(123).substr(1, 1) because Str inherits from Cool (like the classical OOP done backward).
In a similar way, it seems that "100".Int.Complex is like Cool("100").Int.Complex -> Int("100").Complex -> 100.Complex -> Cool(100).Complex -> Complex(100).

Related

Does Perl 6 have an infinite Int?

I had a task where I wanted to find the closest string to a target (so, edit distance) without generating them all at the same time. I figured I'd use the high water mark technique (low, I guess) while initializing the closest edit distance to Inf so that any edit distance is closer:
use Text::Levenshtein;
my #strings = < Amelia Fred Barney Gilligan >;
for #strings {
put "$_ is closest so far: { longest( 'Camelia', $_ ) }";
}
sub longest ( Str:D $target, Str:D $string ) {
state Int $closest-so-far = Inf;
state Str:D $closest-string = '';
if distance( $target, $string ) < $closest-so-far {
$closest-so-far = $string.chars;
$closest-string = $string;
return True;
}
return False;
}
However, Inf is a Num so I can't do that:
Type check failed in assignment to $closest-so-far; expected Int but got Num (Inf)
I could make the constraint a Num and coerce to that:
state Num $closest-so-far = Inf;
...
$closest-so-far = $string.chars.Num;
However, this seems quite unnatural. And, since Num and Int aren't related, I can't have a constraint like Int(Num). I only really care about this for the first value. It's easy to set that to something sufficiently high (such as the length of the longest string), but I wanted something more pure.
Is there something I'm missing? I would have thought that any numbery thing could have a special value that was greater (or less than) all the other values. Polymorphism and all that.
{new intro that's hopefully better than the unhelpful/misleading original one}
#CarlMäsak, in a comment he wrote below this answer after my first version of it:
Last time I talked to Larry about this {in 2014}, his rationale seemed to be that ... Inf should work for all of Int, Num and Str
(The first version of my answer began with a "recollection" that I've concluded was at least unhelpful and plausibly an entirely false memory.)
In my research in response to Carl's comment, I did find one related gem in #perl6-dev in 2016 when Larry wrote:
then our policy could be, if you want an Int that supports ±Inf and NaN, use Rat instead
in other words, don't make Rat consistent with Int, make it consistent with Num
Larry wrote this post 6.c. I don't recall seeing anything like it discussed for 6.d.
{and now back to the rest of my first answer}
Num in P6 implements the IEEE 754 floating point number type. Per the IEEE spec this type must support several concrete values that are reserved to stand in for abstract concepts, including the concept of positive infinity. P6 binds the corresponding concrete value to the term Inf.
Given that this concrete value denoting infinity already existed, it became a language wide general purpose concrete value denoting infinity for cases that don't involve floating point numbers such as conveying infinity in string and list functions.
The solution to your problem that I propose below is to use a where clause via a subset.
A where clause allows one to specify run-time assignment/binding "typechecks". I quote "typecheck" because it's the most powerful form of check possible -- it's computationally universal and literally checks the actual run-time value (rather than a statically typed view of what that value can be). This means they're slower and run-time, not compile-time, but it also makes them way more powerful (not to mention way easier to express) than even dependent types which are a relatively cutting edge feature that those who are into advanced statically type-checked languages tend to claim as only available in their own world1 and which are intended to "prevent bugs by allowing extremely expressive types" (but good luck with figuring out how to express them... ;)).
A subset declaration can include a where clause. This allows you to name the check and use it as a named type constraint.
So, you can use these two features to get what you want:
subset Int-or-Inf where Int:D | Inf;
Now just use that subset as a type:
my Int-or-Inf $foo; # ($foo contains `Int-or-Inf` type object)
$foo = 99999999999; # works
$foo = Inf; # works
$foo = Int-or-Inf; # works
$foo = Int; # typecheck failure
$foo = 'a'; # typecheck failure
1. See Does Perl 6 support dependent types? and it seems the rough consensus is no.

Fortran serialization using C_LOC and C_F_POINTER

I'm looking for a Fortran Library or preferred method of serializing data to a memory buffer in Fortran.
After researching the topic, I found examples using the EQUIVALENCE statement and the TRANSFER intrinsic function. I wrote code to test them and they both worked. In my limited testing, the transfer function seems to be quite a bit slower than the equivalence statement. However, I have found several references stating that in general not to use the equivalence statement.
So, I've been trying to come up with another way to serialize data efficiently. After ready up on the Fortran 2003 spec I discovered that I could use the C_LOC and C_F_POINTER together to cast my "byte" array into the desired data type (int, real, etc..). Initial testing shows that it is working and is faster than the transfer function. An example program is listed below. I was wondering if this is valid use of the C_LOC and C_F_POINTER functions.
Thanks!
program main
use iso_c_binding
implicit none
real(c_float) :: a, b, c
integer(c_int8_t), target :: buf(12)
a = 12345.6789_c_float
b = 4567.89123_c_float
c = 9079.66788_c_float
call pack_float( a, c_loc(buf(1)) )
call pack_float( b, c_loc(buf(5)) )
call pack_float( c, c_loc(buf(9)) )
print '(A,12I5)', 'Bin: ', buf
contains
subroutine pack_float( src, dest )
implicit none
real(c_float), intent(in) :: src
type(c_ptr), intent(in) :: dest
real(c_float), pointer :: p
call c_f_pointer(dest, p)
p = src
end subroutine
end program
Output:
Bin: -73 -26 64 70 33 -65 -114 69 -84 -34 13 70
I also coded this up in Python to double check the answer above. The code and output is listed below.
import struct
a = struct.pack( '3f', 12345.6789, 4567.89123, 9079.66788)
b = struct.unpack('12b', a)
print b
Output:
(-73, -26, 64, 70, 33, -65, -114, 69, -84, -34, 13, 70)
Practically, use of C_LOC and C_F_POINTER in this way is likely to work, but formally it is not standard conforming. The type and type parameters of the Fortran pointer passed to C_F_POINTER must either be interoperable with the object nominated by the C address or be the same as the type and type parameters of the object that was originally passed to C_LOC (see the description of the FPTR argument in F2008 15.2.3.3). Depending on what you are trying to serialize, you may also find that formal restrictions on the C_LOC argument (which are progressively less restrictive in later standards than F2003) come into play.
(The C equivalent requires use of unsigned char for this sort of trick - which is not necessarily the same thing as int8_t.)
There are constraints on the items in an EQUIVALENCE set that make that approach not generally applicable (see constraints C591 through C594 in F2008). Interpreting the internal representation of an object through equivalence is also formally subject to the rules around definition and undefinition of variables - see F2008 16.6.6 item 1 in particular.
The conforming way to access the representation of one object as a different type in Fortran is through TRANSFER. Be mindful that serialization of the internal representation of derived types with allocatable or pointer components (is that what you mean by dynamic fields?) may not be useful.
Depending on circumstance, it may be simpler and more robust to simply store your real time results in an array of the type of the thing to be stored.

Rackunit equality-checking for structs

I'm trying to test out a tokenizer/parser combo for a compiler in racket, and I have a function parse-string, contract-typed to something like (-> string? ast:IntExp) (I know, I should probably rename my structs, but I was experimenting with typed racket for a little while there.
Anyway, I have a test bank written up with stuff like
(check-equal? (parse-string "4") (ast:IntExp 4)), and all of the tests fail, even though upon manual inspection, they look like they ought to pass. All of my structs are defined with define-struct/contract, and all of them are marked #:transparent.
What's going wrong here?
Okay, sorry for not including enough source to be helpful:
Here's the struct definition for IntExp:
(define-struct/contract (IntExp Exp) ([val integer?]) #:transparent)
Here's the test: (check-equal? (parse-string "4") (ast:IntExp 4))
Here's the complaint rackunit gives back:
--------------------
FAILURE
actual: #(struct:IntExp ... 4)
expected: #(struct:IntExp ... 4)
name: check-equal?
location: (#<path:/Users/clem/dev/tiger/parser-lexer-tests.rkt> 8 0 139 48)
expression: (check-equal? (parse-string "4") (ast:IntExp 4))
And, just in case, here's the dependencies I'm requireing:
(require "lexer.rkt"
"parser.rkt"
parser-tools/lex
(prefix-in ast: "ast.rkt")
rackunit)
The actual parser code is kind of large, and I have a hunch that it's not the source of the problem, because all of my tests are failing in this way (the results, upon inspection, seem correct). My bet is that I'm doing something very silly in rackunit.
Racket was using reference-equality because the structs in question inherited from an opaque struct-type. As per the docs, either make the opaque parent structs transparent, or add an
equal?-recur method which compares the underlying structure.

Does fortran 90 (gfortran) optimise array syntax?

I have done a lot of work with array-based interpreted languages, but I'm having a look at Fortran. What has just occurred to me after writing my first bit of code is the question of whether or not gfortran will optimise an expression using array syntax by placing the expression in a single loop. In most array-based interpreters an expression such as A=B/n*2*pi (where B is an array) would require 5 loops and multiple array temporaries to evaluate. Is gfortran clever enough to optimise this out, and will my code below (the line that calculates the array from 0 to 2pi) be as efficient as an explicit do loop around the expression? Is there anything I should look out for when using array syntax if I'm worried about performance?
PROGRAM Sine
IMPLICIT NONE
REAL, PARAMETER :: PI = 3.415926535
INTEGER, PARAMETER :: z = 500
INTEGER :: ier
INTEGER, EXTERNAL :: PGBEG
REAL, DIMENSION(z) :: x,y
x=(indgen(z)-1.0)/z*(2*pi) ! This line...``
y=sin(x)
CALL plot(y,x)
CONTAINS
FUNCTION indgen(n) result(i)
INTEGER :: n
INTEGER, DIMENSION(n) :: i
INTEGER :: l
DO l=1,n
i(l)=l
END DO
END FUNCTION indgen
SUBROUTINE plot(y,x)
REAL, DIMENSION(:) :: x,y
ier=PGBEG(0,'/XWINDOW',1,1)
CALL PGENV(0.0,7.0,-1.0,1.0,0,1)
CALL PGLINE(SIZE(x),x,y)
CALL PGEND()
END SUBROUTINE plot
END PROGRAM Sine
In gfortran you can use the -Warray-temporaries flag to see all array temporaries generated. When I try your example no extra array temporary is generated (other than the one necessary to store the results of indgen(z)), so I guess gfortran is clever enough.
The expression z*(2*pi) is a compile-time constant, which the compiler can easily verify, so that should not be evaluated at run time regardless. Additionally, virtually all modern compilers should perform one-line "elemental" array operations within a single loop, and in many cases SIMD instructions will be generated (auto-vectorization).
Whether a temporary is generated usually depends on whether or not each element can be handled independently, and whether or not the compiler can prove this. Xiaolei Zhu's suggestion of using -Warray-temporaries is a good one. Don't mix this up wih -fcheck=array-temps, which I think only applies to temporaries generated for function calls.
Here's an example of such a message from gfortran:
foo.F90:4.12:
foo(1:20) = 2*foo(20:1:-1)
1
Warning: Creating array temporary at (1)
Your function call will be done in a separate loop, unless the compiler can inline it. Whether or not the compiler inlines a short function can be pretty unpredictable; it potentially depends on where that other function is defined, whether or not the function has the pure attribute (although in practice this rarely seems to matter), the vendor and version of the compiler itself, and the options you pass. Some compilers can generate a report for this; as I recall, the Intel compiler has a decent one.
Edit: It's also possible to inline the expression in this line pretty easily by hand, using an "implied do loop":
x = [ ( real(i)/z*(2*pi), i = 0, z-1) ]
Yes.
Fortran is compiled rather than interpreted.
It handles loops very well.

What is _Complex?

Reading Objective-C type encodings documentation (GCC's and Apple's pages somewhat complement each other), I stumbled upon the _Complex keyword. I've never heard about it, and when I tried to look it up, I found tons of results talking about erroneous uses of it, but never what it really did.
What is _Complex, and how does it work?
A complex number type which looks like it uses half the bit-width for the real part and half for the imaginary part:
_Complex double x; declares x as a variable whose real part and imaginary
part are both of type double.
_Complex short int y; declares y to
have real and imaginary parts of type
short int; this is not likely to be
useful, but it shows that the set of
complex types is complete.
Posts about "EXC_BAD_ACCESS _Complex double return"
http://hintsforums.macworld.com/showthread.php?t=92768
http://developer.apple.com/library/mac/#documentation/DeveloperTools/gcc-4.0.1/gcc/Complex.html
Complex numbers.