Fork me on GitHub
#off-topic
<
2017-07-28
>
qqq08:07:49

so I have been studying racket, and really like the language, including it's builtin match (more than clojure's match), it's macro system, ...

qqq08:07:04

is there any attempt to port racket to clojure (found none successful on github)

schmee09:07:47

@qqq none that I’m aware of. If you really like Racket, why not just use Racket?

qqq10:07:53

jvm and js support

tbaldridge12:07:32

@qqq Hows the immutable data and succession of states story in Racket

qqq13:07:18

@tbaldridge : I think Clojure can learn alot from typed-racket and syntax-parse.

tbaldridge14:07:54

@qqq I find spec to be better than both, honestly.

tbaldridge14:07:22

something like spec (or racket contracts) is much more flexible and powerful than types.

tbaldridge14:07:48

And declarative macro syntax will break down at some point. Spec is an excellent answer for macro input validation as well.

alandipert15:07:44

they seem like all totally different things to me

alandipert15:07:06

and so i'd have trouble considering any of them "better", personally

alandipert15:07:51

i also don't have any experience with any of them... so there's that, lol

roberto15:07:05

I also find comparing them does a disservice to both. They are not directly comparable.

tbaldridge15:07:58

So typed racket is closest to typed Clojure. Racket also has a contract system that has similarities to spec.

tbaldridge15:07:29

So I'm comparing them in the same way I'd compare any type system to spec. Spec is more flexible as you have the full power of the language at hand.

tbaldridge15:07:31

As far as define-syntax bit goes. It works well enough for simple macros that are simple expansion patterns, but more advanced macros will require an escape hatch. With these more advanced macros (like you often need for DSLs) you often end up with a parse phase (which spec handles very well) and an emit phase which is just the creation of some datastructures.

tbaldridge15:07:20

Both typed Clojure and define-syntax for Clojure have been tried several times, but both end up being fairly limiting.

luxbock16:07:00

I think Typed Clojure actually has some #lang like feature in it, though I have no idea if it does anything like what Racket does

qqq16:07:43

I tried typed clojure; it ran fairly slowly for me.

qqq16:07:52

This was on a quad core 16gb machine.

qqq18:07:06

for type checking in general, if the user is asked to provide a type for each function, is that generally enough to infer all the remaining types ?

dpsutton18:07:02

(if true "a" :b) things are gonna get weird even on non user-defined functions. What's the type of this function?

dpsutton19:07:02

clojure will allow things that aren't part of the rigidity required by typed languages, AFAIK

tbaldridge19:07:18

or what's the type of this?

tbaldridge19:07:34

(fn [x] (if (string? x) (keyword x) (str x)))

tbaldridge19:07:46

That's what makes transducers almost impossible to type ^^. The type of the return value of a transducer can depend on the input value, or previous values in the accumulator

dpsutton19:07:39

@qqq you're gonna run into a problem as well. The closing keynote at the seattle clojure/west was about someone doing gradual typing from the racket world and they called it fundamentally broken. it would be worth a watch

dpsutton19:07:14

but basically anytime you leave a rigid world of types and come back all you know about the input is that its object or something similar and that throws off what you can infer going forward

mobileink21:07:04

@tbaldridge: dependent types for Clojure? Wonder if that’s even possible. (I’m reading https://www.manning.com/books/type-driven-development-with-idris)

mobileink21:07:08

maybe spec could do it?

roberto21:07:32

I think that with spec you can specify what conditions you expect the result to be in relation to its input.

roberto21:07:03

and I think you can also say how the inputs are related to each other.

roberto21:07:29

Personally, I prefer types 🙂

tbaldridge21:07:05

@mobileink and of course since you have an entire language behind you (and not a DSL) you can really do anything with spec.

tbaldridge21:07:44

There was a funny talk I saw once by the author of Idris, where he's write a fn type and then hit a Emacs macro that would implement the function given the type

tbaldridge21:07:01

but at that point, aren't you just writing in a dynamic language (a type DSL)?

roberto21:07:14

hmmm, I’d disagree, because you still get compile time checking

roberto21:07:44

you are only leveraging the feedback the compiler is giving you to add just enough code to satisfy it

mobileink21:07:54

well, dependent types are still slightly magical to me, tbh…

roberto21:07:06

and since the compiler tells you the types, it is pretty easy to just add that

tbaldridge21:07:30

but if you put that much info in the types you're just moving the runtime into the compiler

roberto21:07:41

but if you change the function signatures, your code won’t compile, while with dynamic language, it won’t flinch until something goes wrong at runtime

roberto21:07:03

hmm, I wouldn’t say that, you are just making the compiler smarter

roberto21:07:08

and gives your better feedback

mobileink21:07:17

still the possibility of using spec for something approximating real dependent types seems pretty cool

roberto21:07:23

you can still have terrible logic that the compiler won’t help you with

jsa-aerial21:07:35

It doesn't even need to be 'terrible'.

jpmonettas21:07:42

"with dynamic language, it won’t flinch until something goes wrong at runtime" I think a lot of this is mitigated by spec making much easier doing generative testing on fns

roberto21:07:25

that is still an additional effort tho… I prefer the computer to do as much work as possible for me.

roberto21:07:13

I can’t bring myself to using spec because of things like this: `

roberto21:07:27

(s/def ::config (s/*
                  (s/cat :prop string?
                         :val  (s/alt :s string? :b boolean?))))
(s/conform ::config ["-server" "foo" "-verbose" true "-user" "joe"])

roberto21:07:53

s/* …. and this coming from a community that is very vocal about scala’s “obscure” syntax

tbaldridge21:07:12

that's standard regex syntax

tbaldridge21:07:17

you can always write your own macro

roberto21:07:29

scala would say the same thing about some of the things ppl complain about scala

roberto21:07:46

also this: `

roberto21:07:03

(s/fdef with-new-notes
        :args (s/cat :melody ::melody
                     :new-notes (s/coll-of ::note :kind vector?))
        :ret ::melody
        :fn (s/and #(= (-> % :args :new-notes count) (note-count (-> :ret % :notes)))
                   #(= (-> % :args :new-notes) (remove rest? (-> :ret % :notes)))))

roberto21:07:42

I find it more readable if I have something like fun withNewNotes(melody: Melody, newNotes: List<Melody>): Melody

roberto21:07:01

all that extra noise doesn’t give me anything that types will

tbaldridge21:07:02

but that type isn't doing the same thing

roberto21:07:30

that makes my first point ….. it is cryptic

tbaldridge21:07:56

you're comparing apples and oranges though

tbaldridge21:07:11

your type definition doesn't compare the return value to the input value

roberto21:07:22

you can put that inside your logic, or better yet, use dependent types if the type system supports it….

jsa-aerial16:07:00

That's an odd thing to say in this context - then you are right back to runtime checking which seems to be what you just don't want to deal with.

tbaldridge21:07:42

so show me the same with dependant types

roberto21:07:53

my point was: spec is too verbose and cryptic and I find it hard to read code that uses psec

tbaldridge21:07:39

and my point is you're not comparing like things

tbaldridge21:07:13

spec is a much more powerful than java types, and with that power comes a certain level of verbosity

tbaldridge21:07:37

heh, people could even write a DSL for spec that made spec into a Java types-esque thing

roberto21:07:12

fwiw, I was not referring to Java types

tbaldridge21:07:20

but that's what you used

tbaldridge21:07:30

nothing about your function type is more advanced than java

roberto21:07:32

looks like java type, but it isnt

roberto21:07:41

if you want something that shows relation b/w inputs and outputs: `

roberto21:07:47

app : Vect n a -> Vect m a -> Vect (n + m) a
app Nil       ys = ys
app (x :: xs) ys = x :: app xs ys

mobileink21:07:51

i agree spec syntax takes some getting used to, but how is that different than any other?

tbaldridge21:07:27

I agree, I find that definition of app completely unreadable

roberto21:07:28

I find spec less readable because of the noise

roberto21:07:38

yeah, that definition is from the spec docs

tbaldridge21:07:48

and I find idris unreadable because it's all just whitespace and symbols

roberto21:07:54

but I know it is still alpha, so I’m hoping it will improve

tbaldridge21:07:36

To me, the main reason why I don't use a statically typed language is that the moment you touch the outside world, you're untyped. The web isn't statically typed, and trying to force it to be so is just asking for a bunch of pain.

tbaldridge21:07:32

So the moment you hook a program up to the web, a lot of type guarantees go out the window.

tbaldridge21:07:41

So for me, I prefer spec + generative testing.

roberto21:07:43

yeah, I found that to be an issue too when I was just starting to experiment with scala and Kotlin. But I think it made me a better developer because it made me deal with those things up front and isolate the business domain from the outside world. I like how that has turned out and even use the same approach with dynamic languages. So on the interface with the outside world, I format the data in the format the rest of my application expects it to be. It also made me document those expectations up front by encoding them in types.

roberto22:07:21

I used to have a hard time with typed languages but got over it once I decided to slow down and be more delibrate

roberto22:07:57

ironically enough, Rich’s talk about Hammock time was one of those things that made me embrace type systems.

tbaldridge22:07:02

heh, I'm the opposite.

tbaldridge22:07:17

I find type systems to get in the way and keep me from actually writing the code I'm trying to implement

jsa-aerial16:07:49

Your point about nominal vs structural is really spot on to me. It is a major reason why HM like systems (ML, F#, Haskell) always make me think - "This stuff just doesn't capture the semantics of what is going on"

roberto22:07:10

some of your concerns are addressed by more advanced type systems. But yes, in Java I have the same issues you described.

mobileink23:07:48

@tbaldridge re: touching outside world, yeah, after a romance with the heavy-duty typed stuff i've come back to "really great, except when it isn't". still, Idris has a very interesting take on state, concurrency, etc. mind-expanding at the least but i'm not yet sure i would ever use it in anger.

fellshard23:07:40

Could be one of those things where it's very powerful inside a scope in which you have total control, but you gotta bound it with more versatile tools as soon as you start interacting with external systems.

jsa-aerial16:07:49

Your point about nominal vs structural is really spot on to me. It is a major reason why HM like systems (ML, F#, Haskell) always make me think - "This stuff just doesn't capture the semantics of what is going on"