Hacker News new | past | comments | ask | show | jobs | submit | behnamoh's comments login

I want this in Python: https://codecodeship.com/blog/2024-06-03-curl_req

From the article: """

    ~CURL[curl https://catfact.ninja/fact]
    |> Req.request!()
This is actual code; you can run this. It will convert the curl command into a Req request and you will get a response back. This is really great, because we have been able to increase the expressiveness of the language. """


And somewhere there is the logic implemented to know what ~CURL is and what needs to happen with the part in square brackets, how it needs to be translated into a request call. And if that is merely an arguments equals arguments thingy, then it would be kind of useless, since there are usually more things one specifies when making a request from inside Python. Things like headers or whether or not to verify TLS certs, and that is not a 1 to 1 mapping between curl arguments and a requests call.

So I remain doubtful, as long as no way is shown to me, how the user of the language can define this syntactic abstraction themselves, which is unlikely to happen or exist in Python.


Those who still use Common Lisp or some variant of Lisp (other than Clojure), what's your reasoning behind choosing this language over the more mainstream options? I understand that Lisp has some powerful features, but almost everyone that I've talked to holds reservations for those.

For example, Lisp macros are amazing. BUT... this is not good for communicating code in big teams.

Or live (image) programs are an interesting concept, but git versioning them is much more difficult than traditional source code versioning.

Or hot code reloading, which sounds like a powerful concept except that companies would rather log and document their codebase. It also makes it challenging to keep track of the state.

If you force teams not to use macros, then a great reason behind s-exps goes away. And in general, if you take these features away from Lisp, I'm just not sure what use case Lisp can serve.


Lisp macros don’t actually make code harder to read and think about and, unlike the way widely used tools like Flink and Spark do code generation, it’s easy to see what the generated code looks like.

In practices, images are just a deployment tool in CL and most people don’t actually do “version control” by saving and restoring images or using hot code reloading. However, these features enable a development experience that I find much more pleasant than any other language I’ve tried.


I'm actually learning Common lisp for working on my side projects, and those are the reasons that really make the whole thing stick out and amazing.

* Live image and hot-patching is great. You edit it within the code, so if you're making a shooter game, and you're in a "draw HUD" function, you can just edit the code to be what you want and send that function to the running image, to update while you play. Any time you spot a bug, you can isolate, correct, and verify, while still running the game.

* Macros can be thought of as a way to make the code more readable. CL is almost thought of as a "programming language to make programming languages in, so you can solve the problem".

For instance, if you think about any amount of boilerplate. Macros allow you to write it once (because you have to) and then use it in different places at different times. CL makes boilerplate nonexistent.

I do this for wrapping up ncurses functions: to use colours, you must turn on and off certain bits and flags. You can imagine that there's complications when you want to draw a box, or colours text, or coloured underlined text, and there's all sorts of flags and state involved. To write it in C or Python would be a few multi line functions. In lisp it can be made as simple as (with-colours a-colour (draw-text) (with-underline (draw-text))).


> * Live image and hot-patching is great. You edit it within the code, so if you're making a shooter game, and you're in a "draw HUD" function, you can just edit the code to be what you want and send that function to the running image, to update while you play. Any time you spot a bug, you can isolate, correct, and verify, while still running the game.

I think this is an excellent selling point. Many frameworks (e.g. JavaScript frameworks) have file system watching implemented, but it is not the same.


It is not even close to the same. And I think the point is that hot patching.

If you could save a JavaScript file and it would reload just those functions in your running app with out changing state, then that would be closer.

As far as I am aware it is near impossible in every language that isn't lisp


You can reload functions without changing state in, oh, POSIX shell.

I carefully wrote the Basta code (Bash Status Line) to be hot upgradable. https://kylheku.com/cgit/basta/about


>CL is almost thought of as a "programming language to make programming languages in, so you can solve the problem".

https://www.google.com/search?q=lisp+is+a+programmable+progr...


> For example, Lisp macros are amazing. BUT...

> this is not good for communicating code in big

> teams.

I don't know what this means, how is this any different than any other function ? You document it, use it.. I think whoever has said that macros are a problem in teams is imagining problems.

> Or hot code reloading, which sounds like a

> powerful concept except that companies would

> rather log and document their codebase. It also > makes it challenging to keep track of the

> state.

You do the same you would for every language, you have test suites that exercise the code that you need and they need to pass. All code needs to pass on both the local system and CI, again a non issue.

> If you force teams not to use macros

This would be like forcing C++ programmers not to use objects, you could do it but you'd be doing it wrong.

There are many things to pick on common lisp for, but these are not them.

Start with CLOS being to too customizable, the loop macro being its own DSL, and the REPL/live image based development making you annoyed that other repls are considered equal.


The “downsides” you list are actually benefits that non–lisp users try to downplay. Especially macros. Macros give an individual the ability to write things in Lisp that would take a team in any other language. There’s nothing that says a team cannot gain the same multiplier.


The problem is that teams don't consist of the same people for eternity and when new people come in and you have to figure out the three DSLs that an old lisp wizard has cooked up you run into problems. With Lisp one person has the expressiveness of an entire team, but that also means it might take an entire team to figure out what one person did in the first place.

The success of Go stems from the fact that Go code in one place has a 99% chance of looking exactly like it does everywhere else. The power of lisp outsources complexity to readers, the simplicity of a constrained language imposes it on the writers, and because code is read more often than it's written, in a big project consistency beats expressiveness.


That’s how people typically downplay the advantages of Lisp, yes. It’s not really true, but it often works.


and you presumably have an argument for why that isn't true? I've seen exactly this at about three or four companies that had used Clojure. Successively switched to rewrite their codebases in Java because the Clojure codebase became too idiosyncratic as time went on and new workers had trouble being productive in it.

What is it with Lisp advocacy that turns people into religious advocates where market adoption seemingly doesn't matter, because it paints a very clear picture.


If you bring in new people who know Java and don't want to learn anything else, of course the result will be a rewrite in Java.

Not being able to find Clojure people is a problem, but not indicative of any problem with the code itself.


> what's your reasoning behind choosing this language over the more mainstream options?

Well, I could lie and list all of the great features of Lisp that others will have mentioned already, however the real reason I like Lisp is the S-expressions.

It may sound silly, but I really like the structure S-expressions give a program, which gels much better with the way my brain works than more 'conventional' syntax. Other Lispers tend to say that as you go on using Lisp the brackets disappear, but I like the brackets. They give me a sense of structure that I don't get from C, Pascal, Python, or Haskell. I dunno, maybe it's just my autism talking, but there you go.


It looks good to eyes that took a few days getting over their babby duck syndrome.

Has a useful numerical tower containing rational and bignums and an extensive math stdlib to act on them.

A powerful optimizing compiler (available to the user at runtime!) despite the deep dynamism. And pragmas (declarations) much better integrated with the language than in C/C++.

Gradual typing (missing recursive and user-facing parametric typing, I know...).

A stable standard with more than one quality implementation

A pretty good stdlib (missing some stuff due to its age, but well designed in what's there) with some hidden gems like the bitwise manipulation tools or compiler-macros.

https://iterate.common-lisp.dev stomps other languages' idea of imperative iteration.

CLOS/MOP is so flexible the sky's the limit (too flexible, some might say).

I could continue all day, especially if you want the bad and half-baked parts too, but my point is that there are other good points than the "esoteric" features.

Macros are fine and indeed part of the reason to use CL, just don't abuse them.


Common Lisp is the standard, it's ANSI. SBCL is a very robust, very performant runtime, with a pretty sweet price tag.

Sure, you don't want everyone to invent their own personal DSL:s for everything in production, but when you actually need macros the alternative is usually insane amounts of code that is rather inscrutable and quite hard to change across the code base.

And your developers can use the macro system to improve on their personal tooling, eliminating any concerns about it being detrimental to the team while still improving their working environment. You can also use the susceptibility to macros for static analysis and formatting tooling that makes the team's code more homogenous than it would otherwise be, like doped up linters.

You might not want to hot reload in production always, but when you actually need it, it could give a business edge or save the company from an impending catastrophe. It could also help improve working conditions in development and test, testing out patch ideas faster than subsequent builds would allow.


Macros enable communication, rather than hinder it. From the mundane ones defined as part of the language like defun and cond, to frequently helpful patterns like with-foo, to the more expressive ones like pattern matching or even domain-specific ones that can even let non-programmers contribute usefully.

No one versions their save-lisp-and-die blobs like source code, they're effectively binary releases. You could version them as releases.

Hot code reloading is not incompatible with logging, documentation, or normal file-based source control. You may have a misconception that we're just raw-dogging it with typing directly in the REPL window like you're more or less forced to with e.g. Python. Sure, sometimes, but the vast majority of the time no, edits are made to files in a text editor (and often saved) and sent to the REPL as complete forms. It's not challenging to keep track of state, either, especially when you can inspect everything whenever you want, trivially reload an entire system (what I often do after editing more than one file at once), and define more complicated state transforms ahead of time with things like update-instance-for-redefined-class. Rather, it helps avoid keeping track of so much state in your head, because when you're developing something and want to test something out, you just do it, you don't need to restart the application and rebuild the state to just what it was before the point where you wanted to test something different. Additionally, if a company isn't using some sort of hot reloading tool (like JRebel for Java), they're easily wasting 20% or more of developer time. (https://www.jrebel.com/sites/rebel/files/pdfs/rw-mythbusters...)

Besides that: I like dynamic typing, SBCL is default-fast unlike dog-slow Python and Ruby, optional types for speed boosts are there with compiler advice and ready disassembly views to help get and verify the speed (they also add a little bit of compile-time correctness checking, and options like Coalton are readily available for a more Haskell-like experience), the experience of conditions and restarts is way better than exceptions for normal development and debugging, debugging itself is more pleasant despite missing some tools because of the conditions framework and fully dynamic no-compromises hot reloading, code I wrote years ago continues to function, code that was written before I was born continues to function, Lisp's expression of OOP doesn't make me want to rip my hair out, and I rather like the uniformity of s-expressions over having to remember all the l-value/r-value/hidden constructor/operator/conversion/initializations/etc. details of other languages.


>Those who still use Common Lisp or some variant of Lisp (other than Clojure), what's your reasoning behind choosing this language over the more mainstream options?

One programmer can be amazingly productive due to how expressive and flexible the language is. I find my "developer velocity" (eyeroll) is much higher in lisp than in almost any other language.

>Or hot code reloading, which sounds like a powerful concept except that companies would rather log and document their codebase.

I think this is a benefit primarily realized during development cycles. You never "CTRL+C, edit, recompile, run". You just recompile the single function or statement and things just keep on trucking. If your production environment is containerized you'd obviously rarely be hot-reloading, but how often are you changing prod, anyway?


related to this: I want structural editing for non-lisp languages so I don't have to deal with measly lines of code, but with entire trees and branches.

something like this for Python: https://shaunlebron.github.io/parinfer/


For someone who's curious about these topics, do you recommend F# as a language to learn and apply them in practice? I've always thought of Haskell as THE functional programming language because of its purity and elegant syntax which looks very much like math. But lately I've seen people talk about F#, Clojure, ... and I wonder if Haskell is mostly an academic language whereas these are mostly practical?


Those two languages are popular because they bring some of the benefit of languages like Haskell into an environment that is compatible with an outdated but widely used OOP language.

Haskell will bring you more of the benefits from FP with expressive types; Idris will bring you even more. But you will lose the integration.


A lot of people mistake Purity as a language feature for meaning a more pure functional language. What makes a language functional is that their basic unit of abstraction is functions, not whether they isolate IO effects by default.


Impure functions lack referential transparency, which is often sacrificed but kind of important to being a function - getting the same result every time you call it with the same input. Alternatively, you can say that every function has an implicit input parameter of the the current program state, but that turns every function on one bit of input to a potentially astronomically complex function of gigabytes of input.


I do agree with what you're saying about the value of referential transparency and the formal definition of a function as a lambda term. In fact, I work professionally as a Haskell developer and highly value this aspect of the language design; equational reasoning is a really powerful tool.

My point is that functional programming as engineering practice and language family is broader then variants of pure lambda calculi and Haskell occupies one particular place in that broad space.


Haskell focuses on both, but prioritizes research. I have had several Haskell jobs and highly recommend it for the personal enjoyment.


Haskell is far from being an academic language. It’s used in industry and has very practical features and libraries.

Same as F#, OCaml, etc.


F# is not particularly practical as far as jobs go, but it benefits from the large C# ecosystem.

I'm primarily a C# dev, but after dabbling in some F#, I concluded that most of the niceties in F# could also be done (to some extent and with some limitations) on C# as they have the same compile targets.


We seriously need better terminology, notation, and pedagogy when it comes to linear algebra. In 2024, such old-style text books just don't cut it anymore.


What, specifically, do you think should be done better? What style of pedagogy do you think would be more appropriate? What notation? What terminology?

Apart from "argument by year number", what's actually wrong with the book?


As far as I know, this notation and terminology is still very standard.

In some ways I like the idea of replacing traditional indexing with something more like the Einstein summation notation, and moving away from the arbitrary feeling that you get around how matrix multiplication is structured, and provide an immediate route into tensor theory.

But so many things that are very important in linear algebra, like matrix inverses, are awkward to express in this notation.


1. What's wrong with this specific book other than that it hasn't been updated in 7 years?

2. What are examples of better terminology, notation, or pedagogy that are improvements over this book? (Doesn't need to be total, could retain the same terminology and notation but just have better pedagogy for example)


I think interactive linear algebra could be superior to a pure textbook. So, a textbook with interactive visualisations that show a concept and allow manipulation. Something like this maybe: https://textbooks.math.gatech.edu/ila/


That does offer slightly better presentation for students with its interactive elements, but otherwise looks pretty standard for an undergrad linear algebra textbook in overall presentation. It has many sections that could use some interactive portion with none at all.

However, I'll give you that interactive texts (or texts with supplemental interactive material) are often better for some things (and some parts of linear algebra) than a plain dead tree format.


Yeah, I didn't mean this book specifically, rather the presentation as an example.


> a. Lisp isn't a single language, but a family of languages. There's Common Lisp, Scheme, Clojure and even Lisp Flavoured Erlang. They're all similar, but different enough that you can really shoot yourself in the foot if you assume code for one will do the same thing (or even work) in the other. C/C++ have a long history of reverse compatibility and a strong spec that insures interoperability between different implementations (mostly.) Java and C#, for all their perceived faults, have language definitions which are well defined.

This is a really good point. To think that Common Lisp and Clojure are somehow related just because they both use s-exp syntax is like thinking that Java and C# are somehow the same (or compatible) because their syntax is oddly similar.

So the question really is: Why aren't languages that use s-exp more popular? My answer is that s-exp lends itself to homoiconicity. But human brain is actually really good at detecting patterns, and homoiconicity is not compatible with human brain (although it is what computers understand better). Homoiconicity means everything looks the same (code is data), but when everything looks the same, it's hard to detect patterns. Contrast that with C code: just with a glimpse you can tell what each part of the code is doing because functions look different from definitions, etc.

In a weird way, human brain really likes irregularities (i.e., patterns).


>is like thinking that Java and C# are somehow the same

So, perfectly valid?


I guess you use Parinfer and structure editing, which is really cool!


But with parentheses we get the full power of Paredit and Parinfer, is there such a thing for Elixir's ends?


Well, there goes one of the big advantages of open-source models...

For a long time, I was relying on such guaranteed structured outputs as a "secret sauce" that only works using llama.cpp's GBNF grammars. Now OpenAI literally introduced the same concept but a bit more accessible (since you create a JSON and they convert it to a grammar).

Those of you who have used GBNF, do you think it still has any advantage over what OpenAI just announced?


JSON is a sub-set of what GBNF can do, so there are still advantages to that approach. But even GBNF doesn’t go far enough. Ever try to restrict a model to a single sentence?

root ::= \" \" item{{{min_count},{max_count}}}

item ::= [A-Z] [^\\r\\n\\x0b\\x0c\\x85\\u2028\\u2029.?!]+ [a-z] (\". \" | \"? \" | \"! \")

This kinda works if you don't mind no abbreviations, but you can't do something like this with JSON grammars afaik.


FWIW, llama.cpp has always had a JSON schema -> GBNF converter, although it launched as a companion script. Now I think it's more integrated in the CLI and server.

But yeah I mean, GBNF or other structured output solutions would of course allow you to supply formats other than JSON schema. It sounds conceivable though that OpenAI could expose the grammars directly in the future, though.


I think for certain tasks it's still easier to write the grammar directly. Does converting from JSON to a CFG limit the capabilities of the grammar? i.e., are there things JSON can't represent that a context free grammar can?


You might be right that they're similarly powerful. In some cases, an arbitrary output format might in and of itself be desirable. Like it might result in token savings or be more natural for the LLM. For instance, generating code snippets to an API or plain text with constraints.

And this is more esoteric, but technically in the case of JSON I suppose you could embed a grammar inside a JSON string, which I'm not sure JSON schema can express.


greg seems to take a leave of absence, but the way I see it, he's pulling an ilya due to legal reasons. IOW, he's not allowed to found another company for now.


I'm really interested in the reasons behind Greg leaving. IIUC he was doing great engineering related work.


My guess is internal arguing and different vision paths for things.


Gardening leave eh?


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: