Live data from Hacker News

A Haskell Programmer Tries to Learn Racket

artyom.me

141–150 of 163 posts

Re: A Haskell Programmer Tries to Learn Racket

#141

Earlier quoted context omitted.

It's ironic that Haskell is such a language: it grows from a tight, small core into larger and greater abilities as you learn it even without using its extensions. I agree that Common Lisp a very powerful language, but I can't live with all that power uncontrollably thrown on me. Common Lisp grossly lacks self-discipline and self-limitation when it's needed.

I suspect the parent thread was dreaming of a framework where languages with arbitrary syntax can be mixed and matched in user-defined ways. Haskell isn't necessarily that language, partly because it still requires centralized coordination of development of these "extensions" to ensure they're interoperable - that is, there is only one parser for the language and its supported extensions, and many of them are build i…

Yes, Haskell does not allow free syntax extensions composition as easily as Lisp does. But it gets right semantical compositions, using monads for encapsulating semantics and monad transformers to compose effects easily and in a controlled way. I think the latter is much more valuable.

Re: A Haskell Programmer Tries to Learn Racket

#142
post #103

Earlier quoted context omitted.

=> Low barrier to entry means anyone who used to animate jumping monkeys on webpages and now write distributed back-end systems (all web-scale of course). There is nothing distributed about Node. It has IO concurrency, that is all.

I was being sarcastic ;-)

You got me!

Re: A Haskell Programmer Tries to Learn Racket

#143
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 remember DrScheme as it was called before, it was snappy even on old amd duron boxes. DrRacket is very heavy. As other suggested, emacs+geiser gets you quite far. Maybe less nood friendly, because well emacs, no fancy gui artefacts (arrows and such).

Re: A Haskell Programmer Tries to Learn Racket

#144
post #20
post #17

Earlier quoted context omitted.

My theories: 1. Using the same programming language on both sides of HTTP often appeals to a developers visceral sense of elegance, or tidiness, even though it this alone inherently solves no existing problems. 2. It's powered by Googles V8 engine, which means people already associate it with this "super fast JIT" thing that lives in their favourite browser. It must be efficient, right? 3. The crowned alternative is…

1. There is a concrete advantage of shared code.

Which you can get with far better platforms and languages that compile to JS.

And a lot of the use cases aren't sharing code or even have a client/server setup. Like crappy non-parallel build systems being written from scratch using Nodejs.

This thread's been a bit illuminating. I guess I'm not missing anything technical. Some people like JS I guess and Node exists so why not use it.

Re: A Haskell Programmer Tries to Learn Racket

#145

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…

The one good thing about the packaging system is that each dependency is its own version, so you can easily load different versions of the same package.

I'd have to check again, but I looked for specific versions of a JS file and found it repeated multiple times throughout the forest of node_modules.

If side-by-side is desired, then just suffix the folder with a version name. foo.js-1.1 and foo.js-1.0 can be in the root and reused by every package that needs either.

Maybe it does that and I didn't understand what I was looking at.

Re: A Haskell Programmer Tries to Learn Racket

#146

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…

> It's pretty common to want to write something like [. . .] without wanting to destructure a list or use the call-values hack. This makes no sense. You want feature X (the ability to return multiple values) without having to either (a) pick apart a simple structure containing those values or (b) assign names to those values, letting the runtime system pick them apart (or never stick them together, its choice) for yo…

> This makes no sense. You want feature X (the ability to return multiple values) without having to either (a) pick apart a simple structure containing those values or (b) assign names to those values, letting the runtime system pick them apart (or never stick them together, its choice) for you.

I was actually aiming for (b) here, just incorporated directly into the normal function call and return syntax. Why shouldn't you be able to return multiple values in registers or on a results stack without "tupling them up"? It's clearly supported by the hardware. By "call-values" (sp) hack, I meant that needing to use "call-with-values" and "values" is the hack. Lua, for instance, lets you (with very clean syntax) return multiple values from a function, and assign the results to separate variables, during which at no point is an intermediate table constructed:

  thing, err = getthing()
  if thing == nil then print(err) return nil end
  do_stuff(thing)
I don't think I got it quite right with my angular brackets, but I was trying to think of a nice, clear syntax for multiple return values that wouldn't look out of place in a Lisp.

Maybe I was being misleading by using an example that resembled option types. I wasn't trying to bring static typing into this, though I am interested in static type systems and curious about static Lisps, it's just that emulating simple option types for error handling purposes is a very common usage for multiple return values in dynamically typed languages (and, cough, static ones like Go that have lame type systems).

> data Maybe a = Nothing | Just a

> No matter what kind of cleverness you do in memory or whatever, in the end this type is a tuple of two values: (constructor, data).

Is that true? "Maybe" seems like the perfect candidate for a nullable pointer representation, or at least some kind of small tag. I'd be surprised if GHC represents Maybe as a full blown tuple.

Re: A Haskell Programmer Tries to Learn Racket

#147

Earlier quoted context omitted.

Microbenchmarks are fun but silly. I tried to write a similar one for Lua, but LuaJIT ultimately recognized the program was useless and boiled it down to a 3 instruction loop: loop: add ebp, 1 cmp ebp, 10000000 jle loop Anyway, in regards to your results, I could be wrong, but I think I read somewhere that LuaJIT uses linear search for tiny tables for this reason. Dunno what the threshold is, if there is one. The per…

> ... recognized the program was useless and boiled it down to a 3 instruction loop The loop itself is quite useless, why wasn't it also removed ? (Just kidding) I don't have anything agains Lua or hash tables in principle. And of course tables are used in practice in CL code, but they aren't the primary data-structure. > __index can be another table to searched if the lookup on the child fails (which in turn can hav…

> The loop itself is quite useless, why wasn't it also removed ? (Just kidding)

Good question! I guess LuaJIT isn't optimized for programs that don't do anything.

> So, it is an association list implemented using tables, where links are given by the __index property, using a metatable.

I think that's a matter of opinion. It's interesting that being able to form these simple hierarchies is emergent property of alists, but just because Lua provides another mechanism to implement hierarchical lookups, doesn't mean that the language designers were trying to ape alists. If anything, I'd assume that Roberto and company were inspired by Smalltalk's doesNotUnderstand message when they implemented __index metamethods.

Re: A Haskell Programmer Tries to Learn Racket

#148
post #126

Earlier quoted context omitted.

; CL keyword arg syntax, taken from Practical Common Lisp (defun foo (&key (a 0) (b 0)) (+ a b)) (foo :a 1) -> 1 (foo :a 1 :b 2) -> 3 ; hypothetical table keyword arg syntax ; clojure defines commas to be whitespace, you can pretend they aren't there if you want (defun foo ({a: 0, b: 0}) (+ a b)) (foo {a: 1}) -> 1 (foo {a: 1, b: 2}) -> 3 I fail to see why the table syntax would be any less usable or introspectable by…

Basically the syntax for specifying keyword arglists is based on assoc lists. The calling syntax is based on property lists. There is nothing to be gained by hashtables. The Common Lisp keyword syntax actually is a bit more powerful then what your PCL example shows: (defun foo (&key ((var keyword) init var-arg-supplied-p) ...) Generally I think it is a slight mistake to use specific data types in arglists - basically…

> Generally I think it is a slight mistake to use specific data types in arglists - basically mixing syntax and data types.

That's kinda what alists and plists do! They mix up the abstract "map" or "table" data structure (something that maps keys to values) with some concrete implementation of it. '((key . value) (key . value)) and '(key value key value) are literal representations of two particular map-like data structures, whereas {key: value} or {key = value} could have any concrete representation that the language implementer desires.

Maybe I should have dropped the "hash" from "hash table" in my above posts, so that it was clear that I was interested in the syntactic benefit of using one syntax for mapping names to values, and not some imagined efficiency gains from having (read keyword-function-call) include a hash table instead of an alist.

Re: A Haskell Programmer Tries to Learn Racket

#149

Earlier quoted context omitted.

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 T…

I don't understand the argument for using a hash-table for kw-args. Hash tables only win against plists when you don't need to read every single element; when you always need to read every single element, then it's a losing proposition to use a hash-table instead of a plist. Yes I agree with your later comment about syntactic blessing and all, but I think you picked a terrible example by choosing the single place in…

Maybe it was a bad example, but in either case, I would expect a "sufficiently smart compiler" to transform

  (defun fun (a &key (b 0) (c 0)) ...)
  (fun 5 :b 3)
into something like

  (defun fun (a b c) ...)
  (fun 5 3 0)
Whether it does so as a regular macro or as a special form of the compiler doesn't matter, there's no need for there to be any difference in efficiency between representing keyword args with tables or plists.

As I later mentioned in another comment, it was a mistake to talk about hash tables when I was really more interested in the abstract map datatype.

Re: A Haskell Programmer Tries to Learn Racket

#150
post #12
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 love Racket but I have only ever had the same experience with DrRacket. I don't know what it is trying to do, but it brings my modest laptop to its knees.

Interesting... I've never had any problems with DrRacket. What qualifies as a "modest laptop"?
Post reply on HN