Type annotations / better type specs/ merging guards and type annotations

Thanks! Just be warned there’s some major refactoring necessary.

I would hesitate to call it an anti-pattern (except for trying to overextend the language or macro overuse), since it promotes good software development. An anti-pattern is usually something that devs reach for because it on the surface is easy but in the long term results in maintainability or comprehension problems, especially for short term and/or unprofiled gains.

I’m not sure that I will ever use this (on the other hand Dropbox extensively used mypy, so we shall see, especially after I hire my first junior in 2020), but I kind of want to make it to be sure.

As for ugly, I think that’s in the eye of the beholder. I suspect it’s just foreign. Serendipitously, it’s the same syntax as what is used in Julia for gradual typing, so I’m not terribly opposed to it on the grounds that it’s broadly familiar in the FP world.

Ah, got it. Since typing and explicit pattern matching have zero conjunction, the macro might use Module.defines_type?/2 to distinguish these two cases.

That is perfectly describing packing two absolutely different concepts into a single line of code, isn’t it?

Sure thing. I just cannot prepend each sentence I write with IMSO :slight_smile:

3 Likes

I also have the feeling of redundancy, of needing to learn three different DSLs to express one concept — a function’s signature — and seeing lots of boilerplate.

Oh I think I see what you’re saying and I agree. I missed this as a corner case in implementation.

Indeed, you probably shouldn’t compile typespecs to guards, even in say a dev/test environment, because you could wind up creating a series of functions which guard as a “case” statement and work in dev/test but fail in prod because the guards are collapsed.

A better strategy would be to move those guards to inside a lambda injected at the head of the function (which I do anyways). That way the typespecs remain typespecs + typechecking and don’t have any unexpected effects on control flow.

Btw, does your code contain generating @spec or just guards?

Haven’t written the @spec stuff yet, but I don’t think it will be terribly challenging. (I didn’t with zigler, granted the types there being much easier)

I’m sure it isn’t challenging. Just the proposed syntax tells the reader that it’s meant primarily for @spec definition. I agree that guards usually are (and should be) written by hand, so I am against auto-generating them recursively: for tuples and structs. I think, a good rule of thumb is 1 type = 1 guard: if you want a guard to be generated for your (compound) type, please define a guard for it with something like defguard