Live data from Hacker News

Why your REPL experience sucks

srasu.srht.site

51–58 of 58 posts

Re: Why your REPL experience sucks

#51

Non-Clojure user here (but with just enough Lisp experience to make a fool of themselves)... > When Clojure evaluates the symbol router [(an argument)] here, it goes through almost the exact same process as it did for the symbol +, but without checking if it’s a special form. It looks for the var in the current namespace that maps to the symbol router, dereferences it, _and saves the function object it retrieves as t…

No expert on Clojure semantics, but I'm pretty sure what's being discussed is common to almost all runtime environments. When you pass an argument to a function, the function doesn't keep track of the name of whatever you pass, it keeps track of the thing you pass. (A few languages bind late enough that you are essentially passing names during function invocation, but AFAIK not many.) The difference is that when you redefine a function in Clojure, you're not updating the memory location of the old function but updating the function that a given var (one of Clojure's synchronization primitives) points to. The var quote, then, is roughly the equivalent of passing a pointer, while the naked syntax is roughly like passing a dereferenced pointer. I find the "save" language in TFA a bit confusing.

Re: Why your REPL experience sucks

#52

Non-Clojure user here (but with just enough Lisp experience to make a fool of themselves)... > When Clojure evaluates the symbol router [(an argument)] here, it goes through almost the exact same process as it did for the symbol +, but without checking if it’s a special form. It looks for the var in the current namespace that maps to the symbol router, dereferences it, _and saves the function object it retrieves as t…

No expert on Clojure semantics, but I'm pretty sure what's being discussed is common to almost all runtime environments. When you pass an argument to a function, the function doesn't keep track of the name of whatever you pass, it keeps track of the thing you pass. (A few languages bind late enough that you are essentially passing names during function invocation, but AFAIK not many.) The difference is that when you…

Thanks, that makes it a bit clearer.

Re: Why your REPL experience sucks

#53
post #7

A related question is why would you want to reload the entire file/namespace every time you make a change? Coming from a Common Lisp background, I am used to evaluating single forms/functions. I would sometimes re-evaluate the entire namespace, but that would be relatively rare. I switched to Clojure many years ago and followed the same workflow. Then ClojureScript and tools like figwheel came along and I was somewha…

So I am no stranger to CL, but the problem solved in the article isn't actually one that's solved by evaluating less than the whole file at once, and in fact I didn't tell anyone to re-evaluate the whole file at all in this article. The critical idea here is it applies to long-running functions, like a loop, a server, or other things. These, when handed function objects, will not reflect new behavior if you re-evalua…

CL: in a primitive way this can be done with generic functions. Use a generic function object. Redefined methods will be picked up without needing a new function object.

When using symbols, often it is not needed to look up symbol functions. Symbols can be called as functions. In code Lisp often assumes that functions are late bound (unless inlined), so a function call to a global function looks up the function from the symbol at runtime.

Re: Why your REPL experience sucks

#54
post #30

Earlier quoted context omitted.

Have a look at Fred0verflow's videos, for example: * https://www.youtube.com/watch?v=St0_jsPnGAw - analyze some SO HTTP API responses * https://www.youtube.com/watch?v=TaazvSJvBaw - transducers from the ground up I think they are great, crystal-clear examples of REPL-based development.

Oh, I think you misunderstood. I'm literally in the Elixir repl all day every day and do know how I'd don't know how I'd manage without one.

If the Elixir REPL is like a Ruby, Python or Node.js "REPL", then we are not talking about about the same kind of REPL in this context.

I suspect, that the Elixir REPL is more like the Erlang REPL, which might be the same kind as LISP REPLs, but I have no direct experience, I just saw Erlang REPL usage from John Hughes videos.

Re: Why your REPL experience sucks

#55
post #48

Earlier quoted context omitted.

So I am no stranger to CL, but the problem solved in the article isn't actually one that's solved by evaluating less than the whole file at once, and in fact I didn't tell anyone to re-evaluate the whole file at all in this article. The critical idea here is it applies to long-running functions, like a loop, a server, or other things. These, when handed function objects, will not reflect new behavior if you re-evalua…

>The critical idea here is it applies to long-running functions, like a loop, a server, or other things. These, when handed function objects, will not reflect new behavior if you re-evaluate a single function. Do you mind going into more details about what you mean here? In my experience, recursive loops will pick up a new function definition but non-recursive loops will only pick up the definition of a function upon…

The idea is such a long lasting loop would take the function object as an argument and call it repeatedly. Recursive or not (tho in clojure's case definitely not, no tail call optimization), doesn't matter as the lookup happened at the first function call.

Re: Why your REPL experience sucks

#56
post #53

Earlier quoted context omitted.

So I am no stranger to CL, but the problem solved in the article isn't actually one that's solved by evaluating less than the whole file at once, and in fact I didn't tell anyone to re-evaluate the whole file at all in this article. The critical idea here is it applies to long-running functions, like a loop, a server, or other things. These, when handed function objects, will not reflect new behavior if you re-evalua…

CL: in a primitive way this can be done with generic functions. Use a generic function object. Redefined methods will be picked up without needing a new function object. When using symbols, often it is not needed to look up symbol functions. Symbols can be called as functions. In code Lisp often assumes that functions are late bound (unless inlined), so a function call to a global function looks up the function from…

This is kinda my point tho, CL's symbols are the same as Clojure's vars for this purpose. And the comparison between generic functions and multimethods is obvious and correct here as well.

Late binding is irrelevant because all of this is about functions as arguments, not in funcall position.

Re: Why your REPL experience sucks

#57
post #7

A related question is why would you want to reload the entire file/namespace every time you make a change? Coming from a Common Lisp background, I am used to evaluating single forms/functions. I would sometimes re-evaluate the entire namespace, but that would be relatively rare. I switched to Clojure many years ago and followed the same workflow. Then ClojureScript and tools like figwheel came along and I was somewha…

Hot reloading is useful when you're making something related to a React-based UI, which you likely are close to 99% of the time in ClojureScript. I seriously doubt it has anything to do with a lack of REPL experience. I use a traditional editor-connected REPL 100% of the time in Clojure and 0% of the time in ClojureScript. I think most of us doing full-stack Clojure work like that.

I used hot reloading extensively when developing a roguelike in Clojure. It was incredibly helpful to have a tight feedback loop.

Re: Why your REPL experience sucks

#58
post #35

Earlier quoted context omitted.

The kind of repl the author refers to is strictly Lisp-based. Your F# repl wouldn't be any different from a Python or Ruby repl and falls well short of the Lisp/Clojure repl experience which is based on the code-as-data feature of Lisps.

I'd have to check and see, but I know at least some of the features overlap (for example f# lets you send a single function/etc to the repl and update the existing definition. However to the specific point he brought up, I'm not sure if anything like the var capture issue comes into play.

The difference between the Lisp REPL and other, Algol-based programming shells (Node, Python, Ruby etc.) is in the R which stands for Read. The Reader is unique to Lisp since Lisp syntax approximates to an Abstract Syntax whereas other language shells have to parse syntax as raw source code during this first stage. The Eval stage is also different with Lisps.
Post reply on HN