Guest User

Untitled

a guest
Feb 9th, 2022
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.19 KB | None | 0 0
  1. // "type" is an actual type in zig, that being said, here's your
  2. // generics, bro:
  3. fn GPoint(comptime measure: type) type {
  4.     // Shit will be solved compile time unless it can't. This
  5.     // means you can use the language as you'd use the C
  6.     // preprocessor, for instance. In this case, at run time there
  7.     // are no types, so all this bullshit is compile time only.
  8.    
  9.     // This is the target type for computations like len.
  10.     comptime var tt = f32;
  11.     if (measure == f64 or measure == f128)
  12.         tt = measure;
  13.            
  14.    
  15.     return struct {        
  16.         // @This() gives us this type's type :)
  17.         const Self = @This();
  18.        
  19.         x: measure,
  20.         y: measure,
  21.  
  22.         const center = Self{
  23.             .x = @as(measure, 0),
  24.             .y = @as(measure, 0)
  25.         };
  26.  
  27.  
  28.         // Inline functions are always inlined, it's not just a
  29.         // suggestion
  30.         fn len2(p2: GPoint(tt), p1: GPoint(tt))
  31.                     callconv(.Inline) tt {
  32.             return math.sqrt(
  33.                 math.pow(tt, p1.x - p2.x, @as(tt, 2)) +
  34.                     math.pow(tt, p1.y - p2.y, @as(tt, 2)));
  35.         }
  36.  
  37.         // Yes, it's this simple. If you feed it something for which
  38.         // it can't convert shit properly, the compiler will just tell
  39.         // you to fuck off. There aren't any traits or anything like
  40.         // that.
  41.         fn len(p1: Self, p2: Self) measure {
  42.             // I can add type checks to the function itself
  43.             if (tt == measure) {
  44.                 return len2(p1, p2);
  45.             }
  46.  
  47.             // We can mostly just use consts everywhere for free
  48.             return len2(
  49.                 .{ .x = @intToFloat(tt, p1.x),
  50.                   .y = @intToFloat(tt, p1.y) },
  51.                 .{ .x = @intToFloat(tt, p2.x),
  52.                   .y = @intToFloat(tt, p2.y) });
  53.                
  54.         }
  55.     };
  56. }
  57.  
  58. test "generics" {
  59.     const p = [_]GPoint(f64) {
  60.         .{ .x = 10.2, .y = 5.22 },
  61.         .{ .x = 20.1, .y = 3.1 },
  62.         GPoint(f64).center,
  63.         .{ .x = -23.4, .y = 22.5 },
  64.     };
  65.  
  66.     var f = GPoint(f64).len(p[0], p[2]);
  67.     print("{}!\n", .{f});
  68. }
  69.  
  70. // Errors are literally just simple error codes. These are uniquely
  71. // numbered throughout the WHOLE compilation, so there are no
  72. // collisions
  73. const FileError = error {
  74.     InvalidValue,
  75.     OutOfMemory,
  76. };
  77.  
  78. // Use ErrType!Type to specify an error possibility
  79. // !type would mean any error type possible
  80. fn str_join_m(alloc: std.mem.Allocator, data: []const []const u8) FileError![]u8 {
  81.     var len: usize = 0;
  82.     for (data) |str| {
  83.         len += str.len;
  84.     }
  85.  
  86.     // 'try' / catch are just keywords to help with errors, they
  87.     // aren't traditional exceptions.
  88.     const buffer = alloc.alloc(u8, len) catch return FileError.OutOfMemory;
  89.     // This does nothing in this case, but if the function returned
  90.     // with an error, this would run.
  91.     errdefer alloc.free(buffer);
  92.  
  93.     len = 0;
  94.     for (data) |str| {
  95.         std.mem.copy(u8, buffer[len..], str);
  96.         len += str.len;
  97.     }
  98.  
  99.     return buffer;
  100. }
  101.  
  102. test "str_join" {
  103.     const alloc = std.heap.c_allocator;
  104.     const parts = [_][]const u8{
  105.         "Mary ", "had ", "a little ", "lamb" };
  106.    
  107.     const str = try str_join_m(alloc, &parts);
  108.     defer alloc.free(str);
  109.     print("{s}\n", .{ str });
  110. }
  111.  
  112.  
  113.  
  114. fn bad_fn() FileError {
  115.     return FileError.OutOfMemory;
  116. }
  117.  
  118. test "handling_errors" {
  119.     // There are various ways to handle errors and null values:
  120.     // ?type defines a nullable type:
  121.     var x: ?u8 = null;
  122.  
  123.     // Ways to check for null:
  124.     if (x) |val| {
  125.         _ = val;
  126.         // val is of type u8!
  127.     }
  128.  
  129.     // If x is null, val = 0
  130.     // These work with c pointers too.
  131.     const val1 = x orelse 0;
  132.     // Can execute arbitrary code with orelse
  133.     const val2 = x orelse return FileError.OutOfMemory;
  134.     const val3 = x orelse {
  135.         print("x is null brah", .{});
  136.         return FileError.OutOfMemory;
  137.     };
  138.  
  139.     // Use try to automatically return errors that occur, and catch to
  140.     // explicitly handle them
  141.     try bad_fn();
  142.     bad_fn catch |e| {
  143.         _ = e;
  144.     };
  145.  
  146.     _ = val1; _ = val2; _ = val3;
  147. }
  148.  
Add Comment
Please, Sign In to add comment