this post was submitted on 13 Oct 2025
21 points (100.0% liked)

programming

276 readers
1 users here now

  1. Post about programming, interesting repos, learning to program, etc. Let's try to keep free software posts in the c/libre comm unless the post is about the programming/is to the repo.

  2. Do not doxx yourself by posting a repo that is yours and in any way leads to your personally identifying information. Use reports if necessary to alert mods to a potential doxxing.

  3. Be kind, keep struggle sessions focused on the topic of programming.

founded 2 years ago
MODERATORS
 

I get dizzy looking at C-like languages, they just feel incredibly hard to follow compared to an S-expression.

Everything this just so verbose and there's so much negative space between the lines. To be fair, this course is making us program using Java so maybe it has to do more with that.

you are viewing a single comment's thread
view the rest of the comments
[–] Tomorrow_Farewell@hexbear.net 2 points 1 week ago* (last edited 1 week ago) (11 children)

Lisp can be compiled down to machine code.

However, the fact that Lisp relies on a ('classic' GC) means that it will had a mandatory runtime.
AFAIK, Go is compiled, but it does have a runtime nevertheless, so just being (non-JIT) compiled is not enough.

~~I do not have the time to engage with the rest of the reply just yet.~~

EDIT:
Don't really have much to comment on the rest of the reply itself, so, for clarity's sake I'd like to address the following first:
I am taking another look at Lisp's syntax since more than a decade, and I think I understand why I find Lisp rather confusing to look at (or, at least, I can put my finger on one of the factors). The units of code (so to speak) in Lisp are mostly separated by whitespaces, while, in most of the languages that I have dealt with, they are largely separated by punctuation (including parentheses/brackets; with parentheses being an optional separator in some cases). Also, the fact that functions are also only separated from their arguments by whitespaces (rather than anything else) makes code harder to read.

Following that example, for static site generators in C-like languages they have to invent their own DSL for creating templates but for Lisp you don't have that separation.

I'm not sure how this is different from composing HTML code as a string directly (instead of using a template) in C-like languages.

Also this isn't a dig at C or C-replacement languages like C++ or Rust, but to higher level languages that are "like C" in the sense that they are at a higher level of abstraction but use the same metaphor (idk this is hard to explain, basically not Lisp's "data as code"). Basically my gripe is with things like Python or Java and not with C or its replacements itself.

Going to just mention that I have not used Java, but I do dislike Python for its (lack of a) typing system.

"data as code"

Not sure what this means (in the sense of 'how is it different from other languages?').

[–] hello_hello@hexbear.net 1 points 1 week ago (10 children)

I'm not sure how this is different from composing HTML code as a string directly (instead of using a template) in C-like languages.

The difference is that in that case the HTML is programmatically distinct from your programming code. For example, Hugo uses Go as its backend but has its own DSL for creating templates which allows you to use variables set by your sites configuration file as well as do loops and other programatic behavior. Using raw HTML isn't as flexible. Most C-likes have libraries for converting HTML to a data structure that can be manipulated by the language but SXML allows for treating HTML as part of your code with zero abstraction in between because the XML structure works great for s-expressions.

The units of code (so to speak) in Lisp are mostly separated by whitespaces, while, in most of the languages that I have dealt with, they are largely separated by punctuation (including parentheses/brackets; with parentheses being an optional separator in some cases). Also, the fact that functions are also only separated from their arguments by whitespaces (rather than anything else) makes code harder to read.

I find the opposite is true, Units of code in Lisp are symbolic expressions that are delimited by a opening and closing symbol. You really only have to follow the indentation to know when an expression ends or which expressions belong to each other. If you understand the rules of list notation then you can parse any Lisp code everywhere and anywhere (sans un-hygenic macros).

This is lisp's "hello world"

(defun factorial (n &optional (acc 1))
    (if (zerop n) acc
        (factorial (1- n) (* acc n))))

;; < ... > 

Not sure what this means (in the sense of 'how is it different from other languages?').

It refers to https://en.wikipedia.org/wiki/Homoiconicity and it's true that all languages at a basic level are homiconic, but lisp specifically emphasizes that property to allow users to extend the language to any domain they want without having to fundamentally recompile the language to a new specification. The main draw of Lisp is interactive programming where you're writing the program itself within said running program and to me feels like the most free way to program.

[–] Tomorrow_Farewell@hexbear.net 1 points 1 week ago (9 children)

The difference is that in that case the HTML is programmatically distinct from your programming code. For example, Hugo uses Go as its backend but has its own DSL for creating templates which allows you to use variables set by your sites configuration file as well as do loops and other programatic behavior. Using raw HTML isn't as flexible. Most C-likes have libraries for converting HTML to a data structure that can be manipulated by the language but SXML allows for treating HTML as part of your code with zero abstraction in between because the XML structure works great for s-expressions.

Not sure what you mean by 'programmatically distinct from programming code'.
I'm honestly still not seeing a significant difference between using an SXML structure (and having to also convert it later, according to the sxml->dom example from the provided Guile Hoot page), and building a string with HTML code in C-likes. Though, I dislike both approaches, and prefer templates, due to the fact that the environment can assist with HTML syntax that way.

I find the opposite is true, Units of code in Lisp are symbolic expressions that are delimited by a opening and closing symbol. You really only have to follow the indentation to know when an expression ends or which expressions belong to each other. If you understand the rules of list notation then you can parse any Lisp code everywhere and anywhere (sans un-hygenic macros).

I mean, in your example, the first line features several keywords/variables/etc. They are separated by whitespaces (and parentheses), with no punctuation in-between to make their separation clearer, and with no apparent way to discern what sort of thing they are. If I didn't know the context of what factorials are, I would not be able to tell what n was supposed to be, for example.
I think that this criticism has actually been voiced by BeanisBrain here.
Parsing C-like code seems to be much easier.
How readable do you find Lisp in codebases with thousands of lines of code?

but lisp specifically emphasizes that property to allow users to extend the language to any domain they want without having to fundamentally recompile the language to a new specification.

Is this not achievable by just defining functions in most languages?
Also, with regards to metaprogramming, have you taken a look at defining arbitrary syntax via Rust macros?

The main draw of Lisp is interactive programming where you're writing the program itself within said running program and to me feels like the most free way to program.

I have, so far, not found REPL to be more than a novelty, to be honest, and, as far as REPL goes, I prefer Jupyter Notebook (which supports several languages, including Python, C++, Rust; not sure if it supports Lisp or its dialects, though) to the default Lisp REPL. Even then, I quite dislike it.

How do you do debugging big projects with REPL?

[–] lilypad@hexbear.net 3 points 1 week ago (1 children)

How do you do debugging big projects with REPL?

For CL (and SBCL specifically): If youre program is running and youve got slynk or slime or similar loaded into it (neccessary for connecting to e.g. emacs) then when you hit an unhandled condition it will break to an interactive debugger in emacs or whatever text editor is connected. You can then evaluate whatever code you want in whatever stack frame you want, including changing function definitions, and select a restart to call (or just restart from a specific stack frame). Its a very fluid experience, you dont lose program state so i find it good for big projects where you might end up deep in the program and have to rerun it from the toplevel.

[–] Tomorrow_Farewell@hexbear.net 2 points 1 week ago (1 children)

I'm curious about a couple of points:

including changing function definitions

Is one forced to do it with the standard CLI REPL, or can one edit the code more selectively like how it's done with text editors?

and select a restart to call (or just restart from a specific stack frame)

Do I understand it correctly, that the following scenario is possible:

  • Some function is called
  • Somewhere during its execution a break is evaluated
  • A programmer redefines the function
  • The programmer resumes the program's execution from the point where the problematic function (which is now redefined) was called
    ?
[–] lilypad@hexbear.net 2 points 1 week ago

Is one forced to do it with the standard CLI REPL

In emacs, you interact with the image in a smoother fashion than typing at the repl; you write your code in a file like any normal project, and then you can load either that file or a single top level form into the image. While this happens using the repl (or the slynk/slime equivalent) it is done with a single keystroke. So youre working in the files and sending definitions to the image.

Do I understand it correctly, that the following scenario is possible:

  • Some function is called
  • Somewhere during its execution a break is evaluated
  • A programmer redefines the function
  • The programmer resumes the program's execution from the point where the problematic function (which is now redefined) was called?

Close. You cant restart from within a function; if you redefine a function you have to restart from that functions call point in the function that called it. Normally instead of doing this programmers establish restarts (a thing that says how to restart from a certain point, which should handle any cleanup thats needed, etc.). But resuming execution is exactly what happens.

  • condition is signalled (through error, signal, break, etc.)
  • search for an applicable handler and if found, call it. This means the handler is called below the condition signalling function on the call stack, and has access to the entire dynamic extent. Handlers can search for restarts and invoke them, return to a specific point, etc.
  • if one isnt found, invoke the debugger (which can be customized).
  • in the debugger the programmer can inspect stack values, functions and their arguments, and just really tear into all the available information. The programmer can also evaluate code still, and even beyond this they can evaluate code within a specific stack frame (tho this is only really useful for getting local variable definitions that havent been compiled away).
  • make decision on how to fix the issue (generally either invoke a restart (such as "abort to toplevel" or e.g. "retry http request" if working with webdev) or restarting from a specific stack frame or returning a specific value from a specific stack frame).
load more comments (7 replies)
load more comments (7 replies)
load more comments (7 replies)