<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: OneWingedShark</title><link>https://news.ycombinator.com/user?id=OneWingedShark</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Sat, 02 May 2026 07:59:24 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=OneWingedShark" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by OneWingedShark in "Object Oriented Programming in Ada"]]></title><description><![CDATA[
<p>An interesting read, though perhaps it would have benefitted from going the route that made things click. After all, each of the features can be independently achieved, so why not show that _before_ winding around to the "whole bag" of OOP?<p>(1) encapsulation, realized in Ada by private types.<p><pre><code>    Package Geometry is
       Type Point is private;
       Function  Create( X, Y : Integer ) return Point;
       Function  X( Object : Point ) return Integer;
       Function  Y( Object : Point ) return Integer;
       Procedure X( Object : in out Point; Value : Integer );
       Procedure X( Object : in out Point; Value : Integer );
    Private
       Type Point is record
          Data_X, Data_Y : Real:= 0.0;
       end record;
    
       Function  X     ( Object : Point ) return Integer is (Object.Data_X);
       Function  Y     ( Object : Point ) return Integer is (Object.Data_X);
       Function  Create( X, Y : Integer ) return Point   is
         ( Data_X => X, Data_Y => Y);
    End Geometry;
</code></pre>
(2) reuse, realized in Ada via generics.<p><pre><code>    Generic
       Type Item is private;
       One : Item;
       with "*"(Left, Right : Item) return Item is <>;
    Function Generic_Exponent( Base : Item; Exponent : Natural ) return Item;
    -- ...implementation
    Function Generic_Exponent( Base : Item; Exponent : Natural ) return Item is
     (case Exponent is
        when 0 => One,
        when 1 => Base,
        when 2 => Base*Base,
        when others =>
          -- Rule: X**2k = (X**k)**2; X**2k+1 = (X**k)**2 * X.
          (Generic_Exponent(Base, Generic_Exponent(Base, Exponent/2), 2)
            *  (if Exponent mod 2 = 1 then Base else One);
     );
</code></pre>
(3) inheritance, realized with type-cloning.<p><pre><code>    Type Temperature is range -40..2_000;
    Type Probe_Range is new Temperature range -20..200;
</code></pre>
(4) abstract interfaces, without touching OOP, arguably generics.<p><pre><code>    (See above; note how we're depending on the type, a "one value", and a "multiply" operation.)
</code></pre>
(5) type extension, for extending types you finally have to buy into OOP.<p><pre><code>    Type Base is null record;
    Function Text(Object : Base) return String is ("[]");
    
    Type Color is ( Red, Green, Blue, Black, White );
    Type Colored_Thing is new Base with record
       Color_Data : Color := Red;
    end record;
    
    Function Text(Object : Colored_Thing) return String is
      ('[' & Color'Image(Object.Color_Data) & " ]");
</code></pre>
(6) dynamic dispatch.<p><pre><code>    -- Gets text from user.
    Function Prompt return String; -- def elsewhere.
    -- Gets a previously saved object.
    Function Get( Name : String ) return Base'Class; -- def elsewhere.
    Unknown_From_User : Base'Class renames Get( Prompt );
    --...
    -- The following will print "[]" if it is BASE, and
    -- "[ COLOR ]" when COLORED_THING, replacing 'COLOR' with
    -- the textual representation/literal for the value.
    Ada.Text_IO.Put_Line( Unknown_From_User.Text );</code></pre></p>
]]></description><pubDate>Tue, 21 Apr 2026 22:52:15 +0000</pubDate><link>https://news.ycombinator.com/item?id=47855781</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47855781</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47855781</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>I read about a VHDL that used DIANA.  
DIANA was an IR in some Ada compilers; I would imagine that such a common IR would facilitate exactly those test benches with an ease that borders on 'ludicrous'.</p>
]]></description><pubDate>Sun, 19 Apr 2026 17:22:31 +0000</pubDate><link>https://news.ycombinator.com/item?id=47825905</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47825905</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47825905</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>Found the link: <a href="https://github.com/ada-game-framework" rel="nofollow">https://github.com/ada-game-framework</a></p>
]]></description><pubDate>Sat, 18 Apr 2026 18:14:21 +0000</pubDate><link>https://news.ycombinator.com/item?id=47818120</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47818120</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47818120</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>I'm pretty sure you can get the new crate-system to grab/make you a working build.
<a href="https://alire.ada.dev/" rel="nofollow">https://alire.ada.dev/</a></p>
]]></description><pubDate>Sat, 18 Apr 2026 17:18:31 +0000</pubDate><link>https://news.ycombinator.com/item?id=47817623</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47817623</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47817623</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>Ok, so the Form parameter is implementation defined; this was to allow the implementations the 'wriggle room' to interface with the host-system.<p>For GNAT, these two pieces of documentation are instructive:
<a href="https://docs.adacore.com/live/wave/gnat_rm/html/gnat_rm/gnat_rm/the_implementation_of_standard_i_o.html#form-strings" rel="nofollow">https://docs.adacore.com/live/wave/gnat_rm/html/gnat_rm/gnat...</a>
<a href="https://gcc.gnu.org/onlinedocs/gcc-4.9.1/gnat_rm/FORM-Strings.html#FORM-Strings" rel="nofollow">https://gcc.gnu.org/onlinedocs/gcc-4.9.1/gnat_rm/FORM-String...</a>
(This second one is older documentation, but illustrates how platform-specific Form parameters could be used.)<p><pre><code>    Ada.Text_IO.Create (
        File => File,
        Mode => Ada.Text_IO.Out_File,
        Name => "test.txt",
        Form => "shared=no"
      );
</code></pre>
The "maze of alternative package bodies and accompanying conditional compilation logic" is an artifact of C's approach to 'portability' using the preprocessor. Typically, the conditionality should be stable once you abstract it (using the compiler's project-management to select the correct body for a particular configuration) -- As a stupidly trivial example, consider the path separator, for the specification you could have:<p><pre><code>    Package Dependency is
       Package OS is
          Function Separator return String;
       End OS;
    End Dependency;
    -- ...
    Package Dependency is
       Package body OS is separate;
    End Dependency;

    -- Windows
    separate (Dependency)
    Package OS is
      Function Separator return String is ("\");
    End OS;

    -- Classic Mac
    separate (Dependency)
    Package OS is
      Function Separator return String is (":");
    End OS;

    -- VMS
    separate (Dependency)
    Package OS is
      Function Separator return String is (".");
    End OS;

    -- UNIX-like
    separate (Dependency)
    Package OS is
      Function Separator return String is ("/");
    End OS;
</code></pre>
Then in your the rest of your program, you program against the abstraction of DEPENDENCY.OS (and whatever other dependencies you have, likewise), and thus separate out the implementation dependency.</p>
]]></description><pubDate>Sat, 18 Apr 2026 17:04:35 +0000</pubDate><link>https://news.ycombinator.com/item?id=47817500</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47817500</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47817500</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>It's actually really great for anything where you want to be more safe/correct, like banking... and the `TASK` construct makes it really nice for naturally multitasking situations. A couple of the people in the community are putting together gamedev tools/engine.</p>
]]></description><pubDate>Sat, 18 Apr 2026 04:06:25 +0000</pubDate><link>https://news.ycombinator.com/item?id=47813052</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47813052</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47813052</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>Hey, let me encourage you: do it.
You might be surprised at the agreement you get, or at discussions.</p>
]]></description><pubDate>Sat, 18 Apr 2026 03:56:01 +0000</pubDate><link>https://news.ycombinator.com/item?id=47813012</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47813012</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47813012</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>Yep.
And sometimes it's hype over the weirdest things... a good example "dependency injection".<p><pre><code>    Generic
      Type Index   is (<>);                                      -- Any discrete type.
      Type Element is limited private;                           -- Any non-discriminated type.
      Type Vector  is array(index range <>) of element;          -- An array-type of Element, indexed by Index.
      with Function "="(Left, Right: Element) return Boolean <>; -- Equal, defaulted.
      with Function "<"(Left, Right: Element) return Boolean <>; -- Less-than, defaulted.
    Function Generic_Sort( X : Vector ) return Vector;
</code></pre>
Now when we instantiate we can inject '>' in place of the '<', reversing the direction of the sort:<p><pre><code>    Function Sort is new Generic_Sort( Index => Integer, Element => Integer, Vector => Integer_Array, "<" => ">");</code></pre></p>
]]></description><pubDate>Sat, 18 Apr 2026 03:53:12 +0000</pubDate><link>https://news.ycombinator.com/item?id=47812996</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47812996</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47812996</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>To be fair, the file-handling is probably the 'crustiest' part of the standard library. (To use the posix-flags, you use the Form parameter.)<p>The best way to use Ada, IMO, is type-first: you define your problem-space in the type-system, then use <i>that</i> to solve your problem. -- Also, because Ada's foreign-function interface is dead easy, you could use imports to handle things in a manner more amiable to your needs/preferences, it's as simple as:<p><pre><code>    Function Example (X : Interfaces.Unsigned_16) return Boolean
      with Import, Convention => COBOL, Link_Name => "xmpl16";
</code></pre>
You can even put pre-/post-conditions on it.</p>
]]></description><pubDate>Sat, 18 Apr 2026 03:38:28 +0000</pubDate><link>https://news.ycombinator.com/item?id=47812937</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47812937</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47812937</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Ada, its design, and the language that built the languages"]]></title><description><![CDATA[
<p>Pretty much [close enough for government work]; see: <a href="https://stackoverflow.com/questions/7764656/who-is-diana-and-why-wont-she-let-my-database-objects-compile" rel="nofollow">https://stackoverflow.com/questions/7764656/who-is-diana-and...</a></p>
]]></description><pubDate>Sat, 18 Apr 2026 03:23:30 +0000</pubDate><link>https://news.ycombinator.com/item?id=47812876</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=47812876</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47812876</guid></item><item><title><![CDATA[New comment by OneWingedShark in "AdaCore Announces Gnat Pro for Rust"]]></title><description><![CDATA[
<p>> I suspect, though, that memory safety is one of the most important kinds of safety.<p>I don't.
It seems to me like "memory-safety" is a response to the legacy of C and "C-compatibility) WRT poor behavior/respect of types; example: int/address punning, int/boolean punning, array/pointer punning, etc. (NUL-terminated stings could fit here, too as they're a consequence of C's address/array confusion.)<p>Contrary to this, would be correct typing.
Consider SQL-injection and how the "best practice" is to never take data from the user... well we <i>can</i> take data from the user AND ensure there's no possibility of injection:<p><pre><code>    Subtype Numeric is String
      with Dynamic_Predicate => (for all C of Numeric => C in '0'..'9'),
           Predicate_Falure  => raise Constraint_Error with "'" & Numeric &"' is not numeric.";
    --...
    Count : Numeric renames Get_User_Value;
    --...
    return Query("SELECT \* FROM Some_Table WHERE Count=" & Count & ";");
</code></pre>
The above is perfectly safe because the constraint imposed prohibits the SQL-injection... and you can even enforce something like SQL_Escaping:<p><pre><code>  PACKAGE Example IS
    -- The only way to get a value of ESCAPED_STRING is via calling Create.
    Type Escaped_String is private;
    Function Create( X:String ) return Escaped_String;
  PRIVATE
    Type Escaped_String is new String;
    Function Create( X:String ) return Escaped_String is
    ( SQL_Escape(X) );
  END Example;</code></pre></p>
]]></description><pubDate>Mon, 02 Oct 2023 18:33:44 +0000</pubDate><link>https://news.ycombinator.com/item?id=37742463</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=37742463</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37742463</guid></item><item><title><![CDATA[New comment by OneWingedShark in "AdaCore Announces Gnat Pro for Rust"]]></title><description><![CDATA[
<p>> The tool would have to be pretty damn good. And also not introduce business risk or at the very least a minimal business risk.<p>That is actually quite possible.  
Ada is in a really good place as far as that goes: imagine the cost of writing an  IDE (to include compiler) for, say, Ada, PL/SQL, and VHDL -- given the common lineage, you could make a custom internal representations (IR), where each language has a 'Subtype' constraint for its particularity (e.g. `Subtype Ada_IR is General_IR with Dynamic_Predicate => Is_Common(Ada_IR) or Is_Ada(Ada_IR);`, and so on for PL/SQL and VHDL), make these IRs with SPARK proving, as you implement PL/SQL and its query-engine also implement SPARK's proof-tools and SMT-interfaces, proving it as you go, next implement and prove code-gen/HW-synth.<p>Now, put the IDE source through the IDE, and BAM! Now you have a proved IDE+compiler for Ada, PL/SQL, and VHDL giving you a very solid platform. (Also, as you would have a DB-engine onboard, you could populate the IDE with templates and run a query like: SELECT Name, Code FROM Entities WHERE Purpose LIKE “%SCSI%”;... or SELECT Name, Purpose FROM Algorithms WHERE Purpose LIKE “%SORT%” AND Ω <= log_2;.)<p>Also, being Ada-based, you could use Ada's Distributed Systems Annex to distribute portions of the IDE, and/or implement CI/CD as per <a href="https://users.ece.utexas.edu/~perry/work/papers/icsm87.pdf" rel="nofollow noreferrer">https://users.ece.utexas.edu/~perry/work/papers/icsm87.pdf</a></p>
]]></description><pubDate>Mon, 02 Oct 2023 18:16:40 +0000</pubDate><link>https://news.ycombinator.com/item?id=37742229</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=37742229</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37742229</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Writing Linux Modules in Ada (2016)"]]></title><description><![CDATA[
<p>Memory management in Ada is such that you need pointers (and the heap) far, far less than in other languages: the language allows the return of values to objects of unconstrained subtypes to provide the constraints; example:<p><pre><code>    Text : Constant String := Read_Chapter( Book );
</code></pre>
Additionally, nesting DECLARE blocks and subprograms allows a fairly fine-tuned memory-usage/cleanup using the stack. The above example could, for example, be part of an outer DECLARE block, which has an inner DECLARE, perhaps with "Paragraphs : Constant String_Vector := Get_Paragraphs( Text );" in its declarative region and "For Paragraph of Paragraphs loop" in its body... as soon as the block is exited, the stack is popped, reclaiming the used memory. This, in turn, means that the need for heap allocation is greatly reduced.<p>Here's an excellent presentation on Ada's memory management:  <a href="https://archive.fosdem.org/2016/schedule/event/ada_memory/" rel="nofollow noreferrer">https://archive.fosdem.org/2016/schedule/event/ada_memory/</a></p>
]]></description><pubDate>Mon, 28 Aug 2023 16:28:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=37296633</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=37296633</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=37296633</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Six programming languages I’d like to see"]]></title><description><![CDATA[
<p>Honestly, Ada fits a <i>LOT</i> of that bill.<p>The type-system and forced spec/implementation split both work well to catch errors; you can go further with SPARK [proving] and using Pre- and Post-conditions, type-invariants.</p>
]]></description><pubDate>Wed, 13 Jul 2022 21:51:56 +0000</pubDate><link>https://news.ycombinator.com/item?id=32089212</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=32089212</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=32089212</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Six programming languages I’d like to see"]]></title><description><![CDATA[
<p>If you want that same GUI/RAD style, Delphi is still around.</p>
]]></description><pubDate>Wed, 13 Jul 2022 17:42:32 +0000</pubDate><link>https://news.ycombinator.com/item?id=32086148</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=32086148</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=32086148</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Six programming languages I’d like to see"]]></title><description><![CDATA[
<p>The items "A serious take on a contract-based language" & "A language with semantic relations" are covered pretty nicely by Ada's SPARK subset/tools... and the really great thing is that the "aspects" are part of the code and don't "go stale" like annotated comments do.</p>
]]></description><pubDate>Wed, 13 Jul 2022 17:41:13 +0000</pubDate><link>https://news.ycombinator.com/item?id=32086133</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=32086133</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=32086133</guid></item><item><title><![CDATA[New comment by OneWingedShark in "What it feels like when Rust saves your bacon"]]></title><description><![CDATA[
<p>Look at Ada and its error-messages.</p>
]]></description><pubDate>Fri, 24 Jun 2022 17:53:19 +0000</pubDate><link>https://news.ycombinator.com/item?id=31866580</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=31866580</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=31866580</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Designing Low Upkeep Software"]]></title><description><![CDATA[
<p>>>say arrays that "know their own length"<p>><p>> There's a fair amount of C code that does just that and does it for a long time.<p>No, there isn't.<p>There <i>can't</i> be because of how arrays in C degenerate into pointers/addresses; see Walter Bright's "C's Biggest Mistake" -- here: <a href="https://www.digitalmars.com/articles/C-biggest-mistake.html" rel="nofollow">https://www.digitalmars.com/articles/C-biggest-mistake.html</a><p>>> or numeric-types that are range-constrained.<p>> Those don't need astral and can be passed through C ABI just fine.<p>No, they can't.<p>If you're passing a "Positive" through C's ABI you lose the fact that the value can be neither negative, nor zero. (Unless you mean "passed through" as in, "not mangled", but this is setting the bar so low as to be laughable.)</p>
]]></description><pubDate>Mon, 27 Sep 2021 16:40:27 +0000</pubDate><link>https://news.ycombinator.com/item?id=28672902</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=28672902</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=28672902</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Designing Low Upkeep Software"]]></title><description><![CDATA[
<p>> The C language also has a stable ABI, which is basically the ffi for most languages,<p>C is honestly terrible to target/use as FFI, doing so precludes doing things correctly, or more advanced things like... say arrays that "know their own length" or numeric-types that are range-constrained.</p>
]]></description><pubDate>Mon, 27 Sep 2021 03:12:07 +0000</pubDate><link>https://news.ycombinator.com/item?id=28666704</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=28666704</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=28666704</guid></item><item><title><![CDATA[New comment by OneWingedShark in "Designing Low Upkeep Software"]]></title><description><![CDATA[
<p>Look into "SeedForth".</p>
]]></description><pubDate>Mon, 27 Sep 2021 02:57:03 +0000</pubDate><link>https://news.ycombinator.com/item?id=28666634</link><dc:creator>OneWingedShark</dc:creator><comments>https://news.ycombinator.com/item?id=28666634</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=28666634</guid></item></channel></rss>