@@ -288,11 +288,141 @@ say <4/2>.nude; # OUTPUT: «(2 1)»
288
288
289
289
= head1 Allomorphs
290
290
291
- = head2 C < IntStr >
292
- = head2 C < NumStr >
293
- = head2 C < ComplexStr >
294
- = head2 C < RatStr >
295
- = head2 C < MidRatStr >
291
+ L < Allomorphs|/language/glossary#index-entry-Allomorph > are subclasses of two types that can
292
+ behave as either of them. For example, the allomorph L < IntStr > is the subclass of L < Int > and
293
+ L < Str > types and will be accepted by any type constraint that requires an L < Int > or L < Str > object.
294
+
295
+ Allomorphs can be created using L « angle brackets|/language/quoting#Word_quoting:_<_> » , either used
296
+ standalone or as part of a hash key lookup; directly
297
+ using method C < .new > ; and are also provided by some constructs such as
298
+ parameters of L « C < sub MAIN > |/language/functions#sub_MAIN» or, in the case of the L < MidRat >
299
+ allomorph, L < Rational > literals with large denominators.
300
+
301
+ = begin code
302
+ say <42>.^name; # OUTPUT: «IntStr»
303
+ say <42e0>.^name; # OUTPUT: «NumStr»
304
+ say < 42+42i>.^name; # OUTPUT: «ComplexStr»
305
+ say < 1/2>.^name; # OUTPUT: «RatStr»
306
+ say <0.5>.^name; # OUTPUT: «RatStr»
307
+ say <1/99999999999999999999>.^name; # OUTPUT: «MidRat»
308
+ say < 1/99999999999999999999>.^name; # OUTPUT: «MidRatStr»
309
+
310
+ @*ARGS = "42";
311
+ sub MAIN($x) { say $x.^name } # OUTPUT: «IntStr»
312
+
313
+ say IntStr.new(42, "42").^name; # OUTPUT: «IntStr»
314
+ = end code
315
+
316
+ A couple of constructs above have a space after the opening angle bracket. That space isn't
317
+ accidental. Numerics that are often written using an operator, such as C < 1/2 > (L < Rat > ,
318
+ division operator) and C < 1+2i > (L < Complex > , addition) can be written as a literal that doesn't
319
+ involve the use of an operator: angle brackets I < without > any spaces between the brackets and the
320
+ characters inside. By adding spaces within the brackets, we tell the compiler that not only we
321
+ want a L < Rat > or L < Complex > literal, but we also want it to be an allmorph: the L < RatStr > or
322
+ L < ComplexStr > , in this case.
323
+
324
+ If the numeric literal doesn't use any operators, then writing it inside the angle brackets, even
325
+ without including any spaces within, would produce the allomorph. (Logic: if you didn't want
326
+ the allomorph, you wouldn't use the angle brackets. The same isn't true for operator-using
327
+ numbers as some constructs, such as signature literals, do not let you use operators, so you
328
+ can't just omit angle brackets for such numeric literals).
329
+
330
+ = head2 Available Allomorphs
331
+
332
+ The core language offers the following allomorphs:
333
+
334
+ = begin table
335
+
336
+ Type | Allomorph of | Example
337
+ ===========+======================+=================
338
+ IntStr | Int and Str | <42>
339
+ NumStr | Num and Str | <42e0>
340
+ ComplexStr | Complex and Str | < 1+2i>
341
+ RatStr | Rat and Str | <1.5>
342
+ MidRat | Rat and FatRat | <1/99999999999999999999>
343
+ MidRatStr | Rat, FatRat, and Str | < 1/99999999999999999999>
344
+
345
+ = end table
346
+
347
+ Note: there is no C < FatRatStr > type.
348
+
349
+ = head2 Coercion of Allomorphs
350
+
351
+ Keep in mind that allomorphs are simply subclasses of the two (or three) types they represent. Just
352
+ as a variable or parameter type-constrained to C < Foo > can accept any subclass of C < Foo > , so will
353
+ a variable or parameter type-constrained to L < Int > will accept an L < IntStr > allomorph:
354
+
355
+ = begin code
356
+ sub foo(Int $x) { say $x.^name }
357
+ foo <42>; # OUTPUT: «IntStr»
358
+ my Num $y = <42e0>;
359
+ say $y.^name; # OUTPUT: «NumStr»
360
+ = end code
361
+
362
+ This, of course, also applies to parameter L < coercers|/type/Signature#Coercion_Type > :
363
+
364
+ = begin code
365
+ sub foo(Int(Cool) $x) { say $x.^name }
366
+ foo <42>; # OUTPUT: «IntStr»
367
+ = end code
368
+
369
+ The given allomorph is I < already > an object of type L < Int > , so it does not get converted to
370
+ a "plain" L < Int > in this case.
371
+
372
+ Of course, the power of allomorphs would be severely diminished if there were no way to
373
+ "collapse" them to one of their components. Thus, if you explicitly call a method with the name
374
+ of the type to coerce to, you'll get just that component. The same applies to any proxy methods,
375
+ such as calling method L « C < .Numeric > |/routine/Numeric» instead of L « C < .Int > |/routine/Int»
376
+ or using the L « C << prefix:<~> >> operator|/routine/~» instead of
377
+ L « C < .Str > |/routine/Str» method call.
378
+
379
+ = begin code
380
+ my $al := IntStr.new: 42, "forty two";
381
+ say $al.Str; # OUTPUT: «forty two»
382
+ say +$al; # OUTPUT: «42»
383
+
384
+ say <1/99999999999999999999>.^name; # OUTPUT: «MidRat»
385
+ say <1/99999999999999999999>.Rat.^name; # OUTPUT: «Rat»
386
+ say <1/99999999999999999999>.FatRat.^name; # OUTPUT: «FatRat»
387
+ = end code
388
+
389
+ A handy way to coerce a whole list of allomorphs is by
390
+ L < hypering|/language/operators#Hyper_Operators > the appropraite prefix operator:
391
+
392
+ = begin code
393
+ say map *.^name, <42 50e0 100>; # OUTPUT: «(IntStr NumStr IntStr)»
394
+ say map *.^name, +«<42 50e0 100>; # OUTPUT: «(Int Num Int)»
395
+ say map *.^name, ~«<42 50e0 100>; # OUTPUT: «(Str Str Str)»
396
+ = end code
397
+
398
+ = head2 Object Identity
399
+
400
+ The above discussion on coercing allomorphs becomes more important when we consider object
401
+ identity. Some constructs untilize it to ascertain whether two objects are "the same". And while
402
+ to humans an allomorphic C < 42 > and regular C < 42 > might appear "the same", to those constructs,
403
+ they're entirely different objects:
404
+
405
+ = begin code
406
+ # "42" shows up twice in the result: 42 and <42> are different objects:
407
+ say unique 1, 1, 1, 42, <42>; # OUTPUT: «(1 42 42)»
408
+ # Use a different operator to `unique` with:
409
+ say unique :with(&[==]), 1, 1, 1, 42, <42>; # OUTPUT: «(1 42)»
410
+ # Or coerce the input instead (faster than using a different `unique` operator):
411
+ say unique :as(*.Int), 1, 1, 1, 42, <42>; # OUTPUT: «(1 42)»
412
+ say unique +«(1, 1, 1, 42, <42>); # OUTPUT: «(1 42)»
413
+
414
+ # Parametarized Hash with `Any` keys does not stringify them; our key is of type `Int`:
415
+ my %h{Any} = 42 => "foo";
416
+ # But we use the allomorphic key of type `IntStr`, which is not in the Hash:
417
+ say %h<42>:exists; # OUTPUT: «False»
418
+ # Must use curly braces to avoid the allomorph:
419
+ say %h{42}:exists; # OUTPUT: «False»
420
+
421
+ # We are using a set operator to look up an `Int` object in a list of `IntStr` objects:
422
+ say 42 ∈ <42 100 200>; # OUTPUT: «False»
423
+ = end code
424
+
425
+ Be mindful of these object identity differences and coerce your allomorphs as needed.
296
426
297
427
= head1 Native
298
428
0 commit comments