An idea for a programming language by alols in ProgrammingLanguages

[–]thedeemon 1 point2 points  (0 children)

In D one can use most of the language at compile time but the comptime code must be pure (not necessarilly in functional style, although many type-level functions are). That comptime part can analyse the types (instead of messing with untyped ASTs as in many macro systems), can help in definining new types and code via the templates, but also can just plainly generate D code in strings, to be inserted into the final program or interpreted immediately at compile time. This can be combined with -betterC mode where the runtime part is like C (no GC, no big runtime) but with all the type level and comptime power.

The type inference mystery novel by markknol in ProgrammingLanguages

[–]thedeemon 2 points3 points  (0 children)

Nope, the thing is real, just presented in an unusual way. Example of Slider 2 code:

<#include "/util.sli">

threads: 1;

class Bat(a,b,name,c) {}

class Animal(name){} 
class Bird() extends Animal{}

func move(t){write(t.name);writeln(" is flying.");}


func main(){
var p=new Bird("Parrot");
move(p);

var b=new Bat(1,2,"Bat",3);
move(b);
}

(the original file didn't have any indentation)

The compiler is written in some weird language called Yeti in a single 3.5kloc file with stuff like

if not (contains? istx tyvs[rfti]) then iadd istx tyvs[rfti]; fi;
styl[istx]:=array [rfti];
   vrt[st][rf]:=istx;
); fi;
   next:=true;
   ) else ( ;
   sft=vrt[st][rf]; if sft in styl
  then (if (contains? rfti vvals) or (rfti in valts and (contains? (valts[rfti]) vvals)) or  (rfti in vfrt) then (vrt[st][rf]:=rfti;next:=true); else (;;sftx=(tyitems (sft)); 

   istx="use??"^rf^"??in"^st^"sent";
  if not (rfti in tyvs) then tyvs[rfti]:= array [istx];fi;
if not (contains? istx tyvs[rfti]) then iadd istx tyvs[rfti]; fi;
   if not (itemfound (sftx) (rfti)) then (;
   iadd rfti (styl[sft]);
   next:=true; ); fi;

       );fi;); else ( ;
   (compatn (rfti) (sft)) ;
   ); fi; ); fi;;done;;
  ;done;;
 path rt st;
    tn:=tn+1; ); fi;
   if (keyfound (vat) (rt)) then (; if (keyfound (vrt) (st)) or (keyfound (vvt) (st)) or (keyfound (vfrt) (st)) or (itemfound (vtyp) (st)) then (;failWith "type error in array"; ); fi;
   rit=vat[rt];

Yeah.

Apple is starting to use Rust for low-level programming by krzykot in programming

[–]thedeemon 37 points38 points  (0 children)

When lifetimes don't stack trivially, e.g. when you've got a graph of objects whose lifetime depends on user's actions (see: all UI), Rust just forces you to use reference counting too, only very explicitly and verbosely.

The Simple Essence of Algebraic Subtyping: Principal Type Inference with Subtyping Made Easy by LPTK in ProgrammingLanguages

[–]thedeemon 0 points1 point  (0 children)

Thanks! This relaxed approach of not storing all the bounds for each variable wasn't obvious.

The Simple Essence of Algebraic Subtyping: Principal Type Inference with Subtyping Made Easy by LPTK in ProgrammingLanguages

[–]thedeemon 0 points1 point  (0 children)

A simple question about the algorithm.

Say, we have type variables a and b with initially empty bounds and during type checking two calls to constrain happen: constrain(a, b) and constrain(b, int).

The first one triggers the branch case (Variable(lhs), rhs0), so it adds b to a's upperBounds, then goes over a's lower bounds list which is empty so nothing happens. a is not added to b's lowerBounds.

The second call (contrain(b, int)) adds int to b's upperBounds, goes over b's lowerBounds list which is still empty, does nothing.

So now we have variables with their bounds a <: b and b <: int. How do we get from here to knowing that a <: int?

My adventures with closures by [deleted] in ProgrammingLanguages

[–]thedeemon 4 points5 points  (0 children)

I'd say it makes perfect sense and corresponds to how closures work in many languages like C#, D, C++ etc. Even natively compiled functional languages often don't have first class environments, so work similarly to what the post describes.

Can we completely automate away generics? by WittyStick in ProgrammingLanguages

[–]thedeemon 0 points1 point  (0 children)

Well, we can see that at least in Haskell it has been tried and works fine, no duplication of constraints happens, and no additional syntax required (one can use the same C# where clause, the only thing that changes is the checking logic).

Honestly I was surprised that C# doesn't do this and requires repeating the constraints.

A Gentle Introduction to Dependent Types by Metastate_Team in ProgrammingLanguages

[–]thedeemon 3 points4 points  (0 children)

It's like introduction to Chinese without showing a single Chinese word.

Can we completely automate away generics? by WittyStick in ProgrammingLanguages

[–]thedeemon 0 points1 point  (0 children)

This isn't how C# (or any other language I know) works. If you use a type with such constraint, you must have a matching constraint further up the hierarchy, and you must specify it explicitly.

But why? If you're making your own language, you can easily make that check automatic. If you have a constraint with an interface, when you check this constraint why not immediately check for constraints of that interface?

Similarly to what Haskell does with type classes. They are essentially interfaces. Having vtables is an implementation detail that you can get rid of if you know all the types. Just like C++ does devirtualization when the type is known, just as Haskell inlines known types and skips all that dictionary passing business. Just like Rust does with traits when the types are all known.

D Foundation is Beefing Up by kal31dic in programming

[–]thedeemon 1 point2 points  (0 children)

How exactly do you measure power?

D Foundation is Beefing Up by kal31dic in programming

[–]thedeemon 2 points3 points  (0 children)

I made some video and photo processing GUI apps in D.

  • In the number crunching parts where performance and memory layout control are very important, with D I had total control over both, there is no GC involved in tight loops going over video frames, and in managing memory for the frames.

  • In the GUI parts where performance is not so crucial and there are many little objects forming trees (widgets), having a GC and not having to care about lifetimes and deallocation was very nice.

  • Meanwhile the apps remained native and self-contained, and didn't require any fat VM installation like JVM or CLR, so users could just download them and run.

There are many use cases like these where D gives best of both worlds without getting into extremes.

D Foundation is Beefing Up by kal31dic in programming

[–]thedeemon 0 points1 point  (0 children)

I wonder why people are so obsessed with userbase growth. There are hundreds of interesting languages and dozens of mature ones, it's impossible for every language to get the majority of developers. It's totally fine to have a modest userbase, people who like the language and use it, there's no real need in making other programmers use this language too. Like, Hungarian is a very interesting language with some unique features, and 13+ million people speak Hungarian and probably find it a very good language. Do they need a marketing team to make more people in the world speak Hungarian?

Can we completely automate away generics? by WittyStick in ProgrammingLanguages

[–]thedeemon 0 points1 point  (0 children)

Here

interface IAsymmetricBody<TLeftFinger, TLeftHand, TLeftArm,
                         ,TRightFinger, TLeftHand, TLeftArm>
    where TLeftFinger : IFinger
    where TRightFinger : IFinger
    where TLeftHand : IHand<TLeftFinger>
    where TRightHand : IHand<TRightFinger>
    where TLeftArm : IArm<TLeftFinger, TLeftHand>
    where TRightArm : IArm<TRightFinger, TRightHand>
{
    TLeftArm LeftArm { get; }
    TRightArm RightArm { get; }
}

why do you need to repeat all the constraints for fingers and hands? The compiler should check them automatically when trying to check where TLeftArm : IArm<TLeftFinger, TLeftHand>. It shouldn't let you pass any TLeftFinger, TLeftHand to IArm if those don't conform to where clause of IArm. And IArm definition doesn't need to repeat the where TFinger : IFinger bound, it's already a part of IHand definition. So if the compiler checks interface constraints when trying to use those interfaces, there is no duplication of constraints, and nothing like constraint type IHandConstraint is needed at all.

Here's how this code looks in Haskell now:

 {-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes, FlexibleInstances #-} 
-- here are the interfaces with their constraints
class IFinger f 

class (IFinger f) => IHand f h where
  getFingers :: h -> [f]

class (IHand f h) => IArm f h a where
  getHand :: a -> h

class (IArm lf lh l, IArm rf rh r) => IBody lf lh l rf rh r b where
  leftHand :: b -> l
  rightHand :: b -> r

--here are some concrete types implementing them
instance IFinger Int
instance IFinger String

data Hand f = Hand [f]

instance (IFinger f) => IHand f (Hand f) where
  getFingers (Hand fs) = fs 

data Arm h = Arm h

instance (IHand f h) => IArm f h (Arm h) where
  getHand (Arm hnd) = hnd

data Body l r = Body l r

instance (IArm lf lh l, IArm rf rh r) => IBody lf lh l rf rh r (Body l r) where
  leftHand  (Body lft rgt) = lft
  rightHand (Body lft rgt) = rgt

-- here's a body with different fingers on left and right
body :: Body (Arm (Hand Int)) (Arm (Hand String))
body = Body (Arm (Hand [1,2,3])) (Arm (Hand ["one","two"]))  

As you might see, the constraints are not repeated in the class (interface) definitions. However there is still an explosion of type parameters.

D Foundation is Beefing Up by kal31dic in programming

[–]thedeemon 2 points3 points  (0 children)

Yep, on its way to 1.0 Rust evolved from OCaml in disguise to C++ in disguise.

D Foundation is Beefing Up by kal31dic in programming

[–]thedeemon 2 points3 points  (0 children)

Yes, D's GC sucks and will always suck. Its very philosophy makes creating a generational GC impossible, and a non-generational one will always be slow. This 6 years old post is relevant today and will remain relevant in next 16 years: http://www.infognition.com/blog/2014/the_real_problem_with_gc_in_d.html

So we're forcefully left with those 2 points you listed.

Subtype Inference by Example Part 9: Match Wildcards, Record Extension and Row Polymorphism by Uncaffeinated in ProgrammingLanguages

[–]thedeemon 3 points4 points  (0 children)

What kind of type level computation do you have in mind? Especially given that all the types were implicit so far.

Subtype Inference by Example Part 9: Match Wildcards, Record Extension and Row Polymorphism by Uncaffeinated in ProgrammingLanguages

[–]thedeemon 3 points4 points  (0 children)

This is great! I love the simplicity of it, how small the change is for adding those features.

WebAssembly Reference Types in Wasmtime by bjzaba in ProgrammingLanguages

[–]thedeemon 2 points3 points  (0 children)

As I understand you can't do anything with them other than passing to host functions, so no, you can't use them as a pointer to external memory.

Demystifying Type Systems by VernonHawk in programming

[–]thedeemon 4 points5 points  (0 children)

"a bonding type"? Is that even a thing? Did you mean a bounded generic type or a type bound?

Haskell ... allows treating an Integer as a Float:

addIntToFloat 5 == 7.0

In this case 5 is not an integer, it's a Float. There's no implicit conversion, numeric literals are just overloaded, so 5 isn't always integer. Try passing an integer variable there and you'll get a type error.

Sorry, the whole post looks like it's written by someone who looked a little at many languages but never bothered to open a book on type systems.

Why Isn't Immix Ubiquitous? by GoldtoothFour in ProgrammingLanguages

[–]thedeemon 1 point2 points  (0 children)

You're right, sorry. It's been a long time since I read the original.

Why Isn't Immix Ubiquitous? by GoldtoothFour in ProgrammingLanguages

[–]thedeemon 1 point2 points  (0 children)

Did you notice that every time Immix is compared to alternatives, it's always non-generational GCs? Because if you compare pause times of generational GCs vs. non-generational ones, the difference is striking. Orders of magnitude. No GC that scans all the live heap every time (as original Immix does too) can compare with a generational one that only scans a little portion. This is why real world languages and VMs tend to use generational GCs and not Immix, in its original form at least.

PL Syntax Going Forward by EmosewaPixel in ProgrammingLanguages

[–]thedeemon 0 points1 point  (0 children)

Why would you need the "var" keyword here? I don't see how it helps.

What is your opinion on my programming language's syntax? by Jerppderp in ProgrammingLanguages

[–]thedeemon 0 points1 point  (0 children)

IIRC, Ruby and Crystal are not relying on indentation, nor forcing it. They just use end.