Live data from Hacker News

Racket – Lisp beyond Clojure

slides.com

91–100 of 179 posts

Re: Racket – Lisp beyond Clojure

#93

Earlier quoted context omitted.

Looping is fine for imperative languages. It should be the norm for performance sensitive things since that is how the CPU works. It is just easier than trying to make a smart compiler turn your recursion into looping constructions. However, for functional languages you really want TCO to work properly so you can write your algorithms in a properly functional way. And you don't just want self-calls to work, but full…

the CPU is just doing a jump to an instruction at the end of each iteration. When you do tail call recursion you are doing just that. The assembly jumps to a tag and in recursion you jump to a function name, which is also effectively a tag. So it's not really about mapping better to the CPU instructions or anything like that The added benefit is that with tail call recursion you can have mutually recursive function (…

You are forgetting about the function prologue, epilogue, and the maintenance of the various pointers. It certainly isn't as simple as a jump as you imply. To do proper TCO most implementation resort to function trampolines and other self-modifying trickery to get similar to loop-like performance. Within the confines of the JVM, without doing extensive source analysis, I doubt there is even a way to do it.

Re: Racket – Lisp beyond Clojure

#94

Earlier quoted context omitted.

Looping is fine for imperative languages. It should be the norm for performance sensitive things since that is how the CPU works. It is just easier than trying to make a smart compiler turn your recursion into looping constructions. However, for functional languages you really want TCO to work properly so you can write your algorithms in a properly functional way. And you don't just want self-calls to work, but full…

the CPU is just doing a jump to an instruction at the end of each iteration. When you do tail call recursion you are doing just that. The assembly jumps to a tag and in recursion you jump to a function name, which is also effectively a tag. So it's not really about mapping better to the CPU instructions or anything like that The added benefit is that with tail call recursion you can have mutually recursive function (…

[deleted]

Re: Racket – Lisp beyond Clojure

#95

Unhappy with the current state of functional programming. I know I should't be. I have a lot of options. I went to school at UC Berkeley. My first language was Scheme. Then Elisp. CLOS was in the first few too. I really didn't learn C or C++ until second semester. A few months ago I had to pick up enough Scala to figure out what some code did in a project and I wasn't really happy with the language. I realize it is m…

Well, of course you're limiting yourself to lisps (except Scala, about which I share your dislikes). How about F#, which is a very practical functional language with good tooling on all platforms? Or Ocaml, or Haskell?

> good tooling on all platforms

Eh... I've run into loads of trouble with F# and Mono, and with .NET Core you have to deal with platform fragmentation if you use any NuGet packages. Editors are pretty good across platforms now (as long as you stay far away from Xamarin Studio/Mono Develop), but I wouldn't call it "good" for non-Windows platforms.

Re: Racket – Lisp beyond Clojure

#96

Earlier quoted context omitted.

the CPU is just doing a jump to an instruction at the end of each iteration. When you do tail call recursion you are doing just that. The assembly jumps to a tag and in recursion you jump to a function name, which is also effectively a tag. So it's not really about mapping better to the CPU instructions or anything like that The added benefit is that with tail call recursion you can have mutually recursive function (…

You are forgetting about the function prologue, epilogue, and the maintenance of the various pointers. It certainly isn't as simple as a jump as you imply. To do proper TCO most implementation resort to function trampolines and other self-modifying trickery to get similar to loop-like performance. Within the confines of the JVM, without doing extensive source analysis, I doubt there is even a way to do it.

this is outside my field of expertise. Can you give an example of a tail call that needs "trickery"?

I'm not 100% on this, but when you have a tail call I don't think you have to remember the state of the stack frame. "function prologue, epilogue, and the maintenance of the various pointers" aren't god given rules - they're things dictated by something like the C ABI so you can resume the caller. So if you're thinking in terms of C ABI then yes, it's a compiler optimization, but in principle I think it's a zero cost abstraction (though I'd argue that the iterative loop is the actual abstraction)

In tail call recursion you're ensured the caller will never resume!

When you enter a tail-recursive function you save (as you normally would) a return pointer for the program counter and allocate registers/memory for your function arguments. At the end of the function you've done all the computation that that frame will ever do, so you are free to overwrite the argument variables when calling the next iteration/recursive-step. The return pointer doesn't need to be touched at all. Where is the complexity you're talking about?

Re: Racket – Lisp beyond Clojure

#97

Unhappy with the current state of functional programming. I know I should't be. I have a lot of options. I went to school at UC Berkeley. My first language was Scheme. Then Elisp. CLOS was in the first few too. I really didn't learn C or C++ until second semester. A few months ago I had to pick up enough Scala to figure out what some code did in a project and I wasn't really happy with the language. I realize it is m…

I guess I don't understand what the big deal is with tail call optimization. Could someone give an example where it really shines and clojure's loop/recur just doesn't? If you are looking to put time into a programming language that is interesting in and of itself, I'd suggest Haskell.

loop/recur is good for replacing structured loops but tail recursion is more general, since it can replace arbitrary gotos.

One example is given by Guy Steele in "Why Object-Oriented Languages need Tail Calls". Basically, tail recursion lets you keep O(1) stack space even in the face of opaque method dispatching in OO code. https://eighty-twenty.org/2011/10/01/oo-tail-calls

Another required reading are the "Lambda the Ultimate" papers, if you haven't read them yet. The "GOTO" one is particularly relevant here. http://library.readscheme.org/page1.html

Re: Racket – Lisp beyond Clojure

#98

Unhappy with the current state of functional programming. I know I should't be. I have a lot of options. I went to school at UC Berkeley. My first language was Scheme. Then Elisp. CLOS was in the first few too. I really didn't learn C or C++ until second semester. A few months ago I had to pick up enough Scala to figure out what some code did in a project and I wasn't really happy with the language. I realize it is m…

Well, of course you're limiting yourself to lisps (except Scala, about which I share your dislikes). How about F#, which is a very practical functional language with good tooling on all platforms? Or Ocaml, or Haskell?

I don't use too much Windows and Mono sucks from all my previous attempts at using it so that kind of kills F# from what I hear.

I tried OCaml (many) years ago, but it always seemed like a kitchen sink research language.

I like well designed languages. Ones with purpose when they start out. Ones I can see a path for. Languages of accretions (Python, Ruby, Javascript, etc) don't interests me as much unless they are languages of production value (Java). Java start off as a language of purpose (Write-One Run-Anywhere) but soon became a language of accretion. Nobody cares about WORA anymore, server side Java is where it is at now.

Maybe I'll just go back to my little corner of APL called KDB+/Q/K[1][2][3] and wait for a language that really piques my interest.

[1]https://en.wikipedia.org/wiki/Kdb%2B

[2]https://en.wikipedia.org/wiki/Q_(programming_language_from_K...

[3]https://en.wikipedia.org/wiki/K_(programming_language)

Re: Racket – Lisp beyond Clojure

#99
post #88

Earlier quoted context omitted.

Agreed. I have two follow up thoughts: 1. Badly designed functions can do less design damage per-function than badly designed languages per construct, but user-defined functions tend to have much higher volume than both language constructs and their usages. 2. Powerful techniques, including DSLs, lead to denser code. Denser code takes more time to read per unit of code. Total reading time may be either more or less,…

> Badly designed functions can do less design damage per-function than badly designed languages per construct Really? When was the last time you successfully used a C library without reading the documentation?

Straw man. When was the last time you had to check the documentation for the parameter evaluation strategy of a C function call?

I don't think it is a controversial statement than a badly designed macro can do more damage than a badly designed function. I believe that this is true, even normalizing for bad macro systems. This is not a statement against macros, so much as it is a statement to consider when making tradeoffs.

Re: Racket – Lisp beyond Clojure

#100
post #76

Earlier quoted context omitted.

Racket provides delimited continuations. The page you linked to is criticizing undelimited continuations -- including quoting Matthias Felleisen -- and contains a link to the following: http://okmij.org/ftp/continuations/undelimited.html#delim-vs...

Yes I know, but call/cc without any context generally refers to undelimited continuations. Delimited continuations use differently named primitives.

In lisp-like languages I am aware of two implementations of delimited continuations using call/cc (racket and cl-cont) but zero that use shift/reset.
Post reply on HN