Live data from Hacker News

A Haskell Programmer Tries to Learn Racket

artyom.me

51–60 of 163 posts

Re: A Haskell Programmer Tries to Learn Racket

#51

Earlier quoted context omitted.

My question is, given the cons pair is not a meaningful primitive datatype to modern CPUs (can't fit in a register unless you're using 32 bit atoms on a 64 bit CPU, the individual cells cannot be meaningfully manipulated while packed into a single register even in that case...), is there a good reason to use an unrestricted pair/2-tuple/2 element vector for the sexp representation? Would it be "wrong" to remove dotte…

I come from a background using Common Lisp for system and web development so I may see things differently than people who were introduced to it academically. Your code looks great, mine just needed to compile :) The cons pair is a a really powerful primitive data structure, it is the linked list of Lisp. You can build a lot of powerful structures given this great base. I really don't it matters what architecture your…

I mean, it's neat that you can build everything out of cons, in the sense that it's neat that Turing machines and the lambda calculus can perform any computation, but that doesn't mean it's a good idea to so in your code, any more than encoding numbers with Church numerals. Why use alists when you can use hash tables, why use... weird SICP-style struct list things when you could just use structs/vectors, etc.

>Hash Tables are part of the Common Lisp Hyperspec so that is a non issue, they have been first class citizens since before Clojure existed (and are nicely integrated into things like loop)

I'm not that familiar with Common Lisp, but a quick search didn't reveal a syntax for hash table literals, which I would consider to be a prerequisite for calling them first class citizens. There are other funny uses of lists (not improper ones, but still) in Common Lisp, like named procedure arguments[1]. I guess my point is, why encourage these weird constructs in the first place? Sexps are good at representing recursive structure, tables are good at mapping names to values, why not just have both and let them do what they're good at? Obviously Common Lisp is very old and can't be changed after the fact, I'm just trying to imagine the "ideal Lisp," whatever that is.

>Do they really confuse people new to Lisp? car+cdr is a pretty simple concept, when talking to new Lispers they usually don't complain about this.

I wasn't, but I've seen it confuse other people. Either way, it's a wart on the syntax that seems out of place in Scheme (not so in Common Lisp, which has lots of other warts ;))

>I come from a background using Common Lisp for system and web development so I may see things differently than people who were introduced to it academically.

Well, I was introduced to Scheme through SICP, but my motivation for picking it up was more practical than theoretical; I'd heard all the message board talk, Paul Graham essays, etc. proclaiming Lisp to be the most powerful, productive family of programming languages that will turn you into an expert programmer and so on, and wanted in on that ;) Maybe it's more practical to be Getting Shit Done™ instead of worrying about syntactic warts, but I think choosing to not have dotted pairs runs a bit deeper, by forcing the language to promote at least tables to a first class syntactic citizen.

[1] For the unfamiliar, it's something like:

  (message "Text" :style bold :color red)
Reads pretty well, but it still seems wrong to me (ymmv), like it's another spot in the language begging for first class hash tables. In Lua, you'd emulate named arguments by passing a table to the function. I wonder what Clojure programmers do here. This?

  (message "Text" {style: bold, color: red})
Which doesn't make a big deal for readability, but I bet if you want to use a macro or whatever accepts named arguments, it'd be much easier to deal with the one with the real hash table.

Re: A Haskell Programmer Tries to Learn Racket

#52

Earlier quoted context omitted.

I keep flipping back and forth, thinking I don't get it, then thinking others don't get it. Single-threaded JS with callbacks. OK? What am I missing? The only thing Node has going for it is a lot of networking libraries. It's not fast, the async style leads to callback hell, JS is a terrible language, and their package management system is slow and bloated (or at least the packages are)[1]. Yet people think it's some…

Straight from the horse's mouth: "Node is popular because it allows normal people to do high concurrency servers. It's not the fastest or leanest or even very well put together - but it makes good trade offs in terms of cognitive overhead, simplicity of implementation, and performance. I have a lot of problems with Node myself - but the single event loop per process is not one of them. I think that is a good programm…

Such a wonderfully confusing and self-contradictory quote. I love it.

Re: A Haskell Programmer Tries to Learn Racket

#53
post #49

Earlier quoted context omitted.

My question is, given the cons pair is not a meaningful primitive datatype to modern CPUs (can't fit in a register unless you're using 32 bit atoms on a 64 bit CPU, the individual cells cannot be meaningfully manipulated while packed into a single register even in that case...), is there a good reason to use an unrestricted pair/2-tuple/2 element vector for the sexp representation? Would it be "wrong" to remove dotte…

It has pedagogical value to define things in terms of a very small kernel language. You will find things like alists in fairly advanced books on lisp (e.g. Lisp In Small Pieces) simply because it reduces the number of extra concepts you need to explain. It's assumed that the reader can figure out how to make the code cleaner and more idiomatic as long as they understand the ideas being presented. Also I have made use…

>Also I have made use of improper lists in my code, usually when I need to do something with multiple values and I don't want to mess with multiple return values, or if I just want to create a list of tuples for some reason and don't feel like defining an actual struct (can't think of a good example right now...)

I get what you're saying, but isn't this just a shortcoming of the language? It's pretty common to want to write something like

  (define (string-lookup-that-might-fail)
    (if (random)  ))
  (define  (string-lookup-that-might-fail))
without wanting to destructure a list or use the call-values hack. That's a bad example, just pretend there were multiple reasons the lookup could fail.

I totally agree about there being pedagogical value in having a simple core. I'm torn between appreciating minimalism and believing that it's ok to introduce complexity to a language that people will use to get things done every day, so long as it's useful complexity and not just historical accident.

Re: A Haskell Programmer Tries to Learn Racket

#54
post #48

Earlier quoted context omitted.

I come from a background using Common Lisp for system and web development so I may see things differently than people who were introduced to it academically. Your code looks great, mine just needed to compile :) The cons pair is a a really powerful primitive data structure, it is the linked list of Lisp. You can build a lot of powerful structures given this great base. I really don't it matters what architecture your…

I think the parent was saying car and cdr are confusing because they don't actually map to registers (i.e. address register and decrement register). On the other hand you don't have to think too hard about the composed versions of them (caddr, cadar, etc...) but they can easily make your code seem obfuscated. Racket offers both that and first/rest anyway so you can choose which style you prefer.

I don't mind car, cdr, and their composed versions at all. `caddr` is much easier for me to read than `(head (tail (tail ...`

I think their usage is sometimes a code smell (the ad-hoc structs I mentioned), but they're really useful when you want to deal with an "unlispy" list of tokens (say, a parser for a language that isn't Lisp).

Re: A Haskell Programmer Tries to Learn Racket

#55

Web apps are a hack on a hack, yes. But it's kind of ironic he hates Javascript so much when Javascript is a pretty cool programming language heavily influenced by Scheme, which is awfully similar to Racket. But hey, I like people who call it like they see it, and there certainly are some drawbacks to Javascript too.

Javascript is a pretty cool programming language heavily influenced by Scheme. -> I couldn't agree with you more.

There is a Lisp-to-JS compiler (ParenJS). https://bitbucket.org/ktg/parenjs

Re: A Haskell Programmer Tries to Learn Racket

#56
post #10

One note: > Racket's default IDE is better than GHCi and probably on par with Emacs (you almost certainly can configure Emacs to be better than anything, but it's not trivial and people don't bother, while DrRacket provides autocompletion and documentation out of the box). Last I used it (a few years ago), DrRacket was very laggy, so I would find it very hard to use for a serious project. YMMV, maybe it's improved.

I find DrRacket sufficiently fast and sufficiently frustrating. It's very useful for interactive debugging but dependent on the mouse and many Emacs key combinations simply cannot be mapped because of it's CUA interface...and so far as I can tell there is no key-combination that switches focus between the REPL pane and the Editor pane short of closing the other pane. The syntax analysis gets to be a bit much too. On…

I think you can switch panes with C-x C-o, same as the Emacs combo.

Re: A Haskell Programmer Tries to Learn Racket

#57
post #49

Earlier quoted context omitted.

It has pedagogical value to define things in terms of a very small kernel language. You will find things like alists in fairly advanced books on lisp (e.g. Lisp In Small Pieces) simply because it reduces the number of extra concepts you need to explain. It's assumed that the reader can figure out how to make the code cleaner and more idiomatic as long as they understand the ideas being presented. Also I have made use…

>Also I have made use of improper lists in my code, usually when I need to do something with multiple values and I don't want to mess with multiple return values, or if I just want to create a list of tuples for some reason and don't feel like defining an actual struct (can't think of a good example right now...) I get what you're saying, but isn't this just a shortcoming of the language? It's pretty common to want t…

Okay yeah I agree with you there. The pain of destructuring cons cells is somewhat mitigated by the various forms that allow pattern matching, but it's still basically the same.

So I think that is actually a good argument for introducing option types (like Haskell's Either a b) into the language. I think Typed Racket has something like this, but in either case you'd want some nice syntax to handle it as well.

Hash tables make this sort of thing fairly easy though (at least in Racket)

(define h #hash{["a" . 3] ["b" . 5]})

(hash-ref h k "failed")

I think most lisps support this right? I remember seeing something similar in pg's bayesian spam filter code.

Re: A Haskell Programmer Tries to Learn Racket

#58
post #10

One note: > Racket's default IDE is better than GHCi and probably on par with Emacs (you almost certainly can configure Emacs to be better than anything, but it's not trivial and people don't bother, while DrRacket provides autocompletion and documentation out of the box). Last I used it (a few years ago), DrRacket was very laggy, so I would find it very hard to use for a serious project. YMMV, maybe it's improved.

Try the Geiser plugin for Emacs. It allows you to connect to the Racket REPL (either it starts a new instance of Racket, or it can connect to a socket/port).

I'm a Vim user and went through elaborate pains to get Emacs working almost like Vim just so I could go through SICP this way.

Re: A Haskell Programmer Tries to Learn Racket

#59
post #57

Earlier quoted context omitted.

>Also I have made use of improper lists in my code, usually when I need to do something with multiple values and I don't want to mess with multiple return values, or if I just want to create a list of tuples for some reason and don't feel like defining an actual struct (can't think of a good example right now...) I get what you're saying, but isn't this just a shortcoming of the language? It's pretty common to want t…

Okay yeah I agree with you there. The pain of destructuring cons cells is somewhat mitigated by the various forms that allow pattern matching, but it's still basically the same. So I think that is actually a good argument for introducing option types (like Haskell's Either a b) into the language. I think Typed Racket has something like this, but in either case you'd want some nice syntax to handle it as well. Hash ta…

> So I think that is actually a good argument for introducing option types (like Haskell's Either a b) into the language. I think Typed Racket has something like this, but in either case you'd want some nice syntax to handle it as well.

I need to look into Typed Racket more. Ever since I learned the tiny bit of Haskell that I know, I can't help but think that I need ADTs in my parenthesis.

Right at the top of the docs, though, it says that they designed the Typed Racket type system to provide static typing for existing untyped Racket programs. That makes me wonder what a statically typed lisp that wasn't trying to be backwards compatible would look like. I've heard of Shen and Qi but at first glance they (especially Qi) seemed to be drifting too far from Lispy prefix notation goodness for my taste.

> Hash tables make this sort of thing fairly easy though (at least in Racket)

It doesn't really help if you're trying to look up a string, though, because then you can't differentiate between a "good" string and an error string based on their types. That means it won't help for similar string fetching operations either, like making a network request and expecting either a response or a string indicating that the request timed out, the connection couldn't be made, etc.

According to the docs, you can also pass an error continuation to hash-ref instead of a failure string. That's interesting, though I have to admit I have trouble thinking in those terms.

Re: A Haskell Programmer Tries to Learn Racket

#60

Earlier quoted context omitted.

I would definitely watch a video series in which an experienced and talented programmer tried out various programming languages for an hour and gave first impressions, comparisons, etc as they hacked something together during the video.

The idea of a twitch.tv stream sounds interesting, with viewers throwing small problems at the coder to solve as they fumble around with a new language.

Twitch learns themselves a Haskell for great lulz?
Post reply on HN