[HN Gopher] Why Hy?
___________________________________________________________________
Why Hy?
Author : tosh
Score : 138 points
Date : 2022-05-03 11:34 UTC (11 hours ago)
(HTM) web link (docs.hylang.org)
(TXT) w3m dump (docs.hylang.org)
| adg001 wrote:
| So, Hy allows "to freely mix imperative, functional, and object-
| oriented styles of programming."
|
| I wonder: 1/ Shall we mix multiple paradigms of programming in
| the same project? 2/ Should we adopt a single programming
| language that supports multiple programming paradigms and utilise
| single paradigm for each given project, for the sake of
| minimizing the skill set required to the development team and -
| not necessarily -the learning curve?
| pmarreck wrote:
| and any time a language allows this "free mixing", it loses the
| very tangible guarantees of purely-functional languages such as
| immutable data, emphasis on no side effects, etc.
| JasonFruit wrote:
| Hy is a false promise. It looks like a lisp; depending on your
| idea of a Platonic lisp, it may _be_ a lisp --- but it preserves
| Python semantics, including its odd scoping rules, and it doesn
| 't feel like writing actual lisp. Scheme or Common Lisp simply
| feel more coherent, having semantics that make sense with the
| language.
| robonerd wrote:
| I haven't gotten into Hy, but what you say about a 'false
| promise' of lisp reminds me of the impression Fennel left me.
| No cons, compile error for '(), no quasiquoting.. it left me
| wondering where the list processing was.
| giraffe_lady wrote:
| Fennel made a really interesting choice in rigidly sticking
| to the lua semantics.
|
| I think in isolation it would be a fairly bad choice, but in
| practice you get a drop-in replacement for lua that fixes
| every problem with lua.
|
| I wouldn't want any other lisp to work like it does but damn
| I consider that thing my savior at this point. I've come to
| really hate lua and fennel bails me out every time.
| robonerd wrote:
| I suppose I should give Fennel another chance, since I have
| similar feelings towards Lua. Lack of quasiquoting
| particularly does sting though, using quasiquoting to
| construct lua tables seems like it would be nice.
| giraffe_lady wrote:
| There's also that partial implementation of the clojure
| stdlib in fennel that might have it. If not... it does
| have a macro system though I've avoided using it. Macros
| can be a quagmire even in popular well-documented lisps
| which fennel definitely is not either.
| quasarj wrote:
| What is odd about Python scoping rules?
| xigoi wrote:
| Variables are function-scoped, not block-scoped. So you can
| do this: if 2 < 3: s = "Math
| works" else: s = "Math doesn't work"
| print(s)
| gilch wrote:
| I wonder if Hissp would be more to your taste?
| https://github.com/gilch/hissp
| Kodiologist wrote:
| I've been working on Hy since 2016 and I've frequently
| encountered, but never understood, the sentiment that Hy isn't
| a "real Lisp". What makes for a real Lisp? There have been
| dozens (hundreds?) of Lisps over the decades, and if they all
| have a defining characteristic that Hy lacks, I don't know what
| it is. Certainly Lisps have varied in how scoping works, among
| other things.
| mumblemumble wrote:
| Agreed. If odd scoping rules are the problem, we can possibly
| disqualify most lisps that have ever existed. Including all
| of the ones that John McCarthy had a hand in building.
|
| For my part, I had similar "this doesn't feel _quite_ like
| lisp " moments with both Hy and Clojure. And I ultimately
| realized that it's the mere presence of the base platform
| that gets me. With Racket, I'm used to feeling like I'm
| sealed off in my own lispy bubble. With Hy and Clojure, there
| are always bits of Python or Java (read: Not Lisp) hiding in
| the background. Many differences from other well-known lisps
| that I know are attributable to that base platform.
|
| And that's a catch-22 situation. Objectively, they might be
| (and, IMO, are) good design decisions. But they're also
| covered in non-lisp cooties. I don't know why I should expect
| otherwise. Brains are weird.
| Qem wrote:
| I wish there was a IDLE for Hy (HYDLE?), so one could have a
| minimum effort environment setup to get started. What editors
| currently support Hylang syntax highlighting?
| kjuulh wrote:
| emacs has a mode for it: https://github.com/hylang/hy-mode
|
| doom emacs make it easy to get started.
| seanw444 wrote:
| Went to install the package manually to try Hy out. Figured
| it was a niche/small enough language that it wouldn't have
| its own Doom module. I was wrong.
| mark_l_watson wrote:
| I use Emacs and also VSCode. Easy to set up.
| bayesian_horse wrote:
| There is also Calisto Hy and JedHy for Jupyter notebook
| support.
| oleganza wrote:
| Whenever people bring up Lisp syntax, I like to remind everyone
| about io language. Its homoiconicity is inspired by Lisp, and
| almost all good things about Lisp syntax are applied in io, but
| at the same time it avoids this awkwardness that turns away most
| of the people (and turns the remaining minority into zealots :-)
|
| So if you design a language and want to use Lisp-like syntax, I
| recommend to also check out io before steaming ahead.
| spdegabrielle wrote:
| I'd heard that homoiconicity isn't real and there is no
| meaningful definition?
| reikonomusha wrote:
| A language is homoiconic if code in that language is written
| using the syntax of data literals of that language.
|
| In the case of most Lisps, code is written using the syntax
| of list and symbol literals. (There are other literals too,
| of course.) (I (usually) like apples)
|
| is a nested list literal with four symbols. You can think of
| symbols as "interned strings"; they're written without quotes
| for convenience. It's not unlike ["I",
| ["usually"], "like", "apples"]
|
| in Python, except I had to use actual strings instead of
| symbols because Python doesn't ship with a standard symbol
| type.
|
| This is also a nested literal list: (loop
| for i below n do (print i))
|
| but this happens to be a list literal that can be "run" (or
| in Lisp parlance, evaluated) as code.
| cardanome wrote:
| Yeah, Lisps don't have a monopoly in homoiconicity. In addition
| to io, the Rebol family is also worth checking out.
|
| Though I have to admit I can not imagine how a person can be so
| mentally inflexible as to be not able to tolerate Lisp-style
| syntax. I get that Common Lisp might look a bit old-school at
| first glance but something like Clojure is basically designed
| to look aesthetically pleasing.
| jhbadger wrote:
| I played with io some time ago as it was one of the languages
| covered in Bruce Tate's "Seven Languages in Seven Weeks" which
| give an introduction to seven programming languages (Ruby, Io,
| Prolog, Scala, Erlang, Clojure, and Haskell) each with a
| different philosophy. Io seemed an interesting proof of
| concept, but are you actually using it for a real project or
| just to explore?
| simulate-me wrote:
| The first snippet of code I see on that page requires me to
| understand way too much syntax. It's nice to see smaller snippets
| of code when first exploring a new language to decide if it's
| worth the effort to learn the syntax and language features.
| gilch wrote:
| Would you prefer something like this?
| https://hissp.readthedocs.io/en/v0.3.0/lissp_quickstart.html
| spapas82 wrote:
| Does it support some kind of repl driven development similar to
| lisp/clojure? Ie evaluate expressions on a live app and update
| the live up with the new values?
| Kodiologist wrote:
| I'm not familiar with such a feature, but you can certainly run
| a Hy program and edit its state in the REPL at the same time,
| if that suffices.
| billfruit wrote:
| The experience I had with it the last time i tried it was that it
| was syntactically very similar to Clojure, but certain subtle
| differences with it. Close but not being precisely same as
| something else could often result in confusions.
| Kodiologist wrote:
| I've been trying to steer the syntax towards imitating Python
| more than Clojure, the idea being that you frequently need to
| rapidly switch between reading Python and Hy (as when you're
| writing a Hy program while consulting documentation for a
| Python library), so it helps to minimize friction there. Thus
| e.g. `True` must now be capitalized that way, Python-style;
| `true` used to be allowed as well. But whether a more
| Pythonesque Hy is more or less confusing than a more
| Clojuresque Hy is admittedly a matter of taste.
| revskill wrote:
| Most of python system i've seen is full of bugs, lack of
| stability, which causes huge damage from developer resources as
| well as operational costs. It's too hard for a junior Python
| developer to produce a reliable system.
|
| One of the reason as i know is, they have no idea of using unit
| test.
| whycombs wrote:
| I've been using hylang lately to build libraries for my python
| projects. It's a lot of fun, and close enough to Clojure that
| there's very little learning curve.
| vindarel wrote:
| I encourage people to try out Common Lisp because, unlike with
| Hy, you will get: speed, ability to build binaries, truly
| interactive image-based development (yes, more interactive than
| ipython), more static type checks, more language features (no
| closures in Hy last time I checked), language stability... To
| reach to Python libs, you have https://github.com/bendudson/py4cl
| My comparison of Python and CL: https://lisp-
| journey.gitlab.io/pythonvslisp/
| amelius wrote:
| What I look for in a language first is how good the support is
| for concurrency, and especially if it has a good, modern
| concurrent garbage collector.
|
| A quick search brought up this:
|
| https://lisp-journey.gitlab.io/blog/pro-mailing-list-on-comm...
|
| > This was primarily for the lack of good parallel, concurrent
| garbage collectors in Common Lisp implementations. The CL
| version of elPrep was actually still a tad faster than any of
| the C++, Go, or Java versions, but we had to work hard to avoid
| long GC pauses. elPrep allocates a lot of memory, and the pause
| time hurts a lot. We solved this by, basically, disabling the
| garbage collector, and reusing memory manually as much as
| possible, which turned the program into almost a manually
| memory-managed affair.
| throwaway894345 wrote:
| With respect to concurrency, after a lot of experience
| operating async Python services, the thing that I look for is
| _a single, standard, ubiquitous concurrency model_. One of
| the biggest pain points for operating Python systems is some
| transitive dependency making a synchronous I /O call and
| blocking the whole event loop, causing timeouts in unrelated
| endpoints and often bringing the whole system down
| (healthchecks start to fail because the endpoint is blocked
| and then the supervisor kills the whole process/pod/etc).
|
| This doesn't happen in Go or (presumably) languages that run
| on Erlang's BEAM VM because there is no sync I/O (from the
| event loop's perspective, anyway).
| throw10920 wrote:
| > What I look for in a language first is how good the support
| is for concurrency, and especially if it has a good, modern
| concurrent garbage collector.
|
| ...in which case you'll _definitely_ not want to use Python
| either, and so are rather far out of place in this thread.
| amelius wrote:
| Python is a great language, but its design-mistakes
| regarding concurrency are exactly why I'm worried about
| that aspect when looking for a new language.
| vindarel wrote:
| They didn't try Allegro CL's new parallel GC (see comments).
| Otherwise, yeah. It depends on one's use case, I guess.
| ducktective wrote:
| What about other LISPs? Racket? Clojure? What is your view on
| Red language?
| vindarel wrote:
| They feel all limited to me :D I only did serious CL
| development but neither of those two especially attract me:
| they are less interactive (and that's my ideal and a daily
| joy), I don't need the Java ecosystem, I want to be lighter
| on resources... I take news about Red from time to time and
| it's still in its early phases it seems.
| didibus wrote:
| I watched the video from your article:
| https://youtu.be/CNFr7zIfyeM
|
| And as someone who programs in Clojure, I feel the
| interactivity is the same. Maybe I'm missing a detail of
| what he's doing though?
|
| The part you don't have in Clojure (without using a
| library), is the restart options, but he didn't seem to
| ever use them, seems he just looked at the error message,
| and went back to fix the code and re-evaluate his test
| again, and that would be exactly the interactive flow I
| would follow in Clojure.
|
| Am I missing something?
| BaculumMeumEst wrote:
| By using Clojure, you're missing out on reliance on
| poorly maintained ffi libraries, a messy library
| ecosystem where you get randomly surprised by side
| effects from mutability where you weren't expecting it,
| and a poor build system.
|
| I love writing CL but there's a reason it's not enjoying
| wide usage nowadays, and I definitely wouldn't go around
| recommending it to unsuspecting people without heavy
| caveats.
| vindarel wrote:
| ah, I see. There's another shorter one below:
| https://www.youtube.com/watch?v=KsHxgP3SRTs In that one I
| get the debugger, I go to the erroneous function, I re-
| compile it, come back to the debugger and resume
| execution (seeing everything pass). Can you do that in
| Clojure? There's also the typical class change: in CL you
| can alter a class definition and the existing objects are
| (lazily) updated. Also (and it's like the only time I
| tried Clojure) you can't install a Clojure library from
| the Clojure REPL, right? And then, what's explained here:
| https://mikelevins.github.io/posts/2020-12-18-repl-
| driven/
| didibus wrote:
| I probably would need to play with that facility in CL to
| really get a sense of the difference.
|
| In Clojure, you can debug at the REPL, but it doesn't
| drop you in the debugger by default. You'd need to eval
| the function as debug first, then it will drop you into
| the debugger next time the function is called.
|
| And there's no restart system by default, so for example
| you probably wouldn't retry by choosing restart test from
| the exception debugger, you'd just re-evaluate the test
| yourself to have it rerun.
|
| There's a condition restart library, and I played a bit
| with it, but not enough, I was confused about how to go
| about choosing options to handle the condition or how to
| define them.
|
| So the typical flow in Clojure would be:
| 1. Error thrown 2. Go to line of code that threw
| error 3. Fix code 4. Eval fixed code
| 5. Eval the thing that threw the error again (seeing
| everything pass)
|
| And if you want to observe the state at the place of the
| error thrown you'd add between 2 and 3:
| 2.1 Eval function as debug 2.2 Re-eval thing that
| threw error 2.3 When in debugger inspect all
| locals and state, find the problem
|
| And then go to 3.
|
| I never really looked into if there was a way to make
| eval as debug default with break on error, then I guess
| you'd get a very similar flow, except for missing the
| restart options.
|
| > There's also the typical class change: in CL you can
| alter a class definition and the existing objects are
| (lazily) updated
|
| Since Clojure isn't OO, this isn't a 1:1 comparison. But
| the closest thing to OO is polymorphic facilities, except
| they don't have state. Anyways, you can update the
| implementation of the polymorphic methods and it gets
| picked up for existing types or data that were
| polymorphic over them.
|
| You can also add more polymorphic methods and those get
| picked up automatically.
|
| There is a construct that has fields on it, but it's
| almost never used, so I actually don't remember if it
| would let you update fields on existing instances, I
| believe not. In CL can you add/remove fields on the class
| and the existing instances get updated? What happens to
| new fields how are they initialized in that case?
|
| > you can't install a Clojure library from the Clojure
| REPL, right?
|
| Well, you can, but let's say that it's something that
| easily breaks, so let's call it a "beta" feature. Some
| people use it effectively and don't seem to have issues,
| but others seem to always have it not work as expected,
| so a lot of people restart the REPL most likely when they
| want to add a lib.
|
| Also, it's not a standard feature of Clojure, instead
| it's a feature of your build tool, either Leiningen or
| Tools.deps, and both have a different way to do it.
| Though tools.deps is the default dependency manager that
| comes with Clojure now, and its add-lib feature should
| one day get out of beta and become permanent, probably
| once they iron out the quirks.
|
| https://practical.li/clojure-staging/alternative-
| tools/cloju...
| vindarel wrote:
| > In CL can you add/remove fields on the class and the
| existing instances get updated? What happens to new
| fields how are they initialized in that case?
|
| yes, and you can even specialize built-in methods so that
| the update does exactly what you want O_o See update-
| instance-for-redefined-class. It takes as arguments the
| added slots, the discarded ones, it's supposed to do the
| right thing but we can customize it.
| didibus wrote:
| Ah I see, ya that's a pretty neat feature for an OO
| language.
|
| You wouldn't get that in Clojure for defining types,
| since they'd be Java types and then they only get what
| features the Java runtime allows on types and it doesn't
| have that one.
|
| But in practice, since Clojure is functional, it's kind
| of a non-issue.
|
| I should really try CL to be sure, but it seems you'd get
| 95% or more of the same interactivity in Clojure.
|
| What I can tell you is I find Clojure superior to Emacs
| LISP in interactivity (which I've used both extensively).
| Emacs can technically redefine more things inside-out,
| like it can do the full runtime rebuild from the example
| link, but because it isn't functional and immutable
| first, managing the state as you redefine things tends to
| be more complex, and I find that makes it less
| interactive, since I need to do a lot of state setup and
| teardown to get things back to what I want to re-
| evaluate.
| pcr910303 wrote:
| Admittedly I've never seriously investigated Clojure
| debugging tools so it might be that Clojure already
| supports something similar; but the Debugging Common
| Lisp[0] series might showcase how Common Lisp (with
| signals, restarts, mechanisms for redefining classes, p
| and more...) and SLIME aids debugging in how other
| 'usual' languages don't.
|
| [0]: https://malisper.me/category/debugging-common-lisp/
| Kodiologist wrote:
| Hy has closures. They work just like Python's.
|
| (Common Lisp is super cool, though. Perhaps one day Hy will be
| as cool.)
| vindarel wrote:
| oopsy, thanks, I was thinking about let (discussed below).
| (yep, I tried Hy but not for long, since I needed something
| more than Python)
| mrtranscendence wrote:
| Common Lisp is great, I'm sure, but it's a bit of a nonstarter
| for me because most of my work is Spark ETL and machine
| learning. I can theoretically sneak some hy in for low-
| visibility code but I can't do the same for Common Lisp.
|
| > no closures in Hy last time I checked
|
| I don't know when the last time you checked was, but as far as
| I can tell hy definitely has closures. It largely follows
| Python semantics, after all.
| vindarel wrote:
| If you're (very) motivated you could try MGL or CLML!
| https://github.com/melisgl/mgl -
| https://github.com/mmaul/clml -
| https://github.com/CodyReichert/awesome-cl#machine-learning
|
| MGL's auhor [won](https://github.com/melisgl/higgsml) the
| Higgs Boson ML Challenge.
| lf-non wrote:
| Can you elaborate on how CL provides more static type checks ?
| I am not much familiar with CL, but does it provide something
| similar to typed-racket ? Do major libraries actually use it ?
| vindarel wrote:
| Not so easy question, especially because it depends of the
| implementation, but SBCL gives pretty good static type errors
| and warnings. Mostly, you get warnings at the function
| boundaries. It isn't complete like type checking in the
| modern languages, but it helps catch many errors. And quickly
| & interactively, because we compile our functions as we write
| them, with a keystroke (or the whole file, and from time to
| time, we build the whole project from scratch). So, coming
| from Python, that was superbly useful to me. This, everybody
| uses it. We can also add gradual typing to our variables and
| functions. It might help for the static checks, and it also
| gives hints for the compiler to speed things up. We can also
| declare our own types, but these won't be used for compile-
| time inference.
|
| For a type-racket equivalent, we now have Coalton, it's like
| a Haskell on top of CL: https://github.com/coalton-
| lang/coalton/ Its author says:
|
| --
|
| Take this with a grain of salt, because I'm neither a user
| nor expert of Typed Racket, but: Typed
| Racket focuses more on the gradual typing of a given program.
| It has lots of features to make that easier, such as
| occurrence typing. Coalton is a separate, embedded language.
| Typed Racket achieves polymorphism through subtyping and and
| first-order type variables. Coalton achieves polymorphism
| through type variables, higher-kinded types, and type
| classes. Coalton, like ML and Haskell, focuses on
| defining objects by their properties and supported functions.
| This is a proposed way of having modular, reusable code.
| Typed Racket, as far as I can tell, has no such features.
| Coalton code can be fully inferred, so type annotations are
| not necessary. Typed Racket cannot.
|
| All in all, I think the biggest and most important take-away
| is that Typed Racket goes through great effort to seamlessly
| blend with ordinary Racket. But that means Typed Racket has
| to compromise on type system features that can only be
| supported if you're willing to change the language itself.
|
| Coalton puts the type system first, opting for something
| close to Haskell, at the expense of not being a system for
| gradually typing Common Lisp, and instead being a separate
| language altogether.
|
| ---
|
| They use it for their open-source quantum compiler and other
| things.
| lf-non wrote:
| Coalton looks interesting - hadn't heard of it before.
| emptysongglass wrote:
| This reads out of touch with why curious people use Hy, like me
| who wanted to get going with an easily accessible language and
| ecosystem (Python) while rewriting bits in Hy to grok some lisp
| magic.
|
| No, of course I wouldn't have reached for CL first and it's
| disappointing to read the top-comment is this.
| IshKebab wrote:
| But... by using Hy you're already learning a new super niche
| language. If you're going to learn a new language why not
| ditch Python and use something good?
|
| Ecosystem size is really the only thing I can think of.
| emptysongglass wrote:
| Because I write Python to plug into a bigger ecosystem and
| I can mix and match Python and Hy freely. I can also use
| Poetry to package and manage dependencies and Poetry2nix to
| output a Nix derivation that is guaranteed to run on
| someone else's machine. I can also freely tap Python
| packages like Beautiful Soup or use frameworks like Django
| (which I am). The entire Python universe is available to
| me. The number of accessible tutorials for Django, videos
| for Pythonistas and community support channels is
| monumentally large. I even get to do cool things like use
| Django's ORM for learning how to interact with and
| manipulate data in Postgres, all right there available to
| me.
|
| I can use Discord (despite my distaste for it as a platform
| it has a _huge_ Django and Python community), Telegram,
| IRC, and Matrix to ask for help and get metric tonnes of
| friendly advice, suggestions and criticisms from
| Pythonistas.
|
| And I can take all of this at my own pace, writing only
| bits in Hy and branching as I go. Every step is as gradual
| as I want it to be.
|
| Common Lisp is not the answer to my needs. Presenting it as
| so is tone deaf at the least.
| vindarel wrote:
| BTW, about Postgres, data, web app... pgcharts, that
| turns queries into charts:
| https://github.com/dimitri/pgcharts is written in CL :)
| Speaking of Postgres, pgloader was re-written from Python
| to CL, here's why: https://tapoueh.org/blog/2014/05/why-
| is-pgloader-so-much-fas...
| vindarel wrote:
| but who's presenting CL as the answer to your needs?
| (me?)
|
| If you're happy with your mix of Python and Hy, well,
| great. But you know what, you can do what you described
| with CL too! Need to do some webscraping? Beautiful Soup
| -> lquery. Django -> well... no CL framework gives you
| all these batteries included, but what if you want to
| extract data from a Postgres DB and display it in a web
| app? that's very easy [1] in CL too. Django ORM ->
| postmodern or Mito (or more). IDK about Nix but several
| people are working with CL and Guix.
|
| https://github.com/CodyReichert/awesome-cl
|
| What worked out for me was to write companion services in
| CL, instead of extending my big Django app. This new
| service that takes data from a FTP server, transforms it,
| stores it, displays it in a web app? CL. That web app
| that serves another kind of customers than the Django
| one? A CL app. It isn't for everybody and sometimes you
| wish for a bigger ecosystem, but anyways, many things can
| be done in CL.
|
| [1]: ok honestly the learning process was not that easy.
| It's a bit easier with my contributions now! (Cookbook
| etc)
| stingraycharles wrote:
| There are two "ecosystems" at topic here: the language
| you're writing code in, and the environment that it's being
| executed in. In this case, you're writing Hy that's
| executed in a Python language environment, that allows you
| to tap into its entire ecosystem with Hy (in a similar way
| like Clojure and the JVM). These types of "alternative
| front ends" are a great way to bridge the gap for a new
| language.
|
| As such, for Hy's target audience, I think it's not as much
| "ditch a new language" as it is "I have to use Python for
| $reason, but I want something more like CL". A good example
| of this would be any machine learning related work.
|
| Last but not least, I would expect that on HN we focus a
| bit more on "what could make Hy even better" rather than
| "what other languages are better than Hy".
| aeturnum wrote:
| I think you're misunderstanding the appeal of ecosystems
| here. It's not just about install base - it's about the
| mental load of adjusting to a new set of assumptions and
| paradigms for interacting with the computer.
|
| To me, the way to think about "introducing" someone to Lisp
| and helping them understand the choices the language makes
| - you really want to focus on the things that make Lisp
| stand out, and one way of doing that is re-using a lot of
| the functionality of a language that outsiders may be
| familiar with.
|
| I generally agree that if you want to build something
| substantial you probably would choose CL over Hy, but if
| you want to "try a lisp" while minimizing startup costs and
| you have a Python background I think Hy makes way more
| sense.
| reikonomusha wrote:
| I don't want to devolve into any petty arguments about
| what makes a Lisp a "Lisp", since everybody has their own
| incompatible definition, but I will say writing Hy feels
| like writing Python with weird syntax, and it does not
| feel like writing Lisp with a huge, familiar ecosystem of
| libraries.
|
| I will give you this, though, you can have a taste macros
| with Hy, which of course are one of the cornerstones of
| different Lisps.
|
| With that said, I do not feel like one would accurately
| develop a feel for what Lisp is like (be it Common Lisp,
| Scheme, Racket, or Clojure) by using Hy.
| aeturnum wrote:
| > _I don 't want to devolve into any petty arguments
| about what makes a Lisp a "Lisp",_
|
| Very much agree! I shouldn't have framed it that way.
|
| I should have said: each time you make a hybrid language
| between approaches, there are new people who will try it
| out and may discover a new and exciting way to program.
| Some people, in hindsight, will certainly wish they had
| jumped further - but they can always do that in the
| future and some will only make the bigger jump after
| making a smaller one.
| cjohnson318 wrote:
| On top of that, just figuring out which Lisp to start
| with, and how to get started with it, is an ordeal. In
| the JVM ecosystem, Java is pretty obvious, and Kotlin is
| a pretty obvious alternative. In the Lisp ecosystem, the
| well known SCIP is targeted at Scheme, Clojure is pretty
| well known, then there's Racket, ChezScheme, CommonLisp,
| and the they all look like pretty good starting places.
| mumblemumble wrote:
| It's an expensive choice to make, too. It quickly becomes
| apparent that, no matter which lisp you choose, there
| will always be a group of people trying to convince you
| that you picked the wrong one, and pressuring you to
| second-guess yourself.
| reikonomusha wrote:
| You're saying it's expensive because... people on non-
| topical forums might tell you their opinion, uninformed
| of your circumstances?
|
| If you choose language X, I advise learning it alongside
| people who know and use X. It seems like a no-brainer to
| me, and not all that expensive.
| mumblemumble wrote:
| It's expensive because seeing that kind of stuff as a
| potential newcomer to a community can have a way of
| psyching a person out and making them think they need to
| be extra careful about this decision.
|
| Basically, that "if you choose..." advice is for the
| wrong context, specifically because of the "if you
| choose" qualifier. I'm talking about what happens during
| the pre-choice time period.
| reikonomusha wrote:
| I don't want to diminish the challenges newcomers have
| with interacting with people online, but we have to
| understand that even _choosing Lisp_ is going to be met
| with significant derision _from people who don 't write
| Lisp_ since it's not a top-10 language. "Lol just use
| Python it's the second best at everything," is a common
| refrain to people who are trying in earnest to learn
| something new and nonstandard for a change.
|
| While I won't claim _nobody_ has been "psyched out" by a
| community of people for their language-learning choices,
| I just don't think that this is something that happens
| with Lisp particularly often. The subreddit r/Lisp is
| predominantly Common Lisp, but more frequently than not
| accepts viewpoints from Clojure, Scheme, Racket, and even
| NewLisp programmers all in the same comment section,
| without bickering.
|
| As I said, if anybody wants to learn a new technology,
| and that somebody is a social person, finding a
| supportive community is important. If somebody going to
| be a novice at a particular language, and broadcast
| opinions about that language on disparate forums--some
| opinions which may come across as uninformed--sure,
| people will likely come out of the woodwork to correct
| them, suggest allegedly superior technology, etc.
| alimov wrote:
| Why is it disappointing? It's just a suggestion (take it or
| leave it), and links out to an interesting and well written
| article.
| pmarreck wrote:
| possibly because i've been playing with Guix lately, and also
| because all the smartest people I know seem to use lisp-likes,
| I'm on team "just use a Lisp" (possibly with some sort of API
| interface to Python)
| gilch wrote:
| No closures? Hasn't it always had them?
| catchclose8919 wrote:
| Which CL "interactive development" feature can't you get with
| either a jupyter notebook or ipython + autoreload enables? With
| a smart editor like VSCode or Spyder you also get visual
| variable inspections, history of executed code in one way or
| another etc. Only that can't easily save an "image" auto-
| magically, but data science and ML people wouldn't want to do
| this other than explicitly (eg. using fast loading formats like
| feather to reload semi-processed vars etc.).
|
| I don't think you are aware how much the Python workflows of AI
| / ML / datasci people resemble you "common lisp ideal" ...but
| with a different language and better libraries :)
|
| And if Julia succeeded, it will also bring decent performance
| to such workflows.
|
| Sure, the way backend devs or devops people use Python is very
| static and different, but any experienced ML practitioners are
| at home with "interactive development".
| reikonomusha wrote:
| Re-define a class and have all objects automatically get
| updated to reflect the changes.
|
| Evaluate arbitrary expressions mid-stack trace.
|
| Run into a bug, get caught in an error, re-define the
| offensive function interactively, and re-run the computation
| before that point, _all without stopping and restarting_.
|
| (Example real-world use-case: You re-define one of your REST
| API endpoints without having to restart your server or
| interrupt the request-flow, be it in test or--if you so
| desire--in prod.)
|
| Change the class of an object at run-time.
|
| Re-compile and re-load individual functions _from your editor
| with your production, git-committed code_. This one is huge.
| You use interactive and incremental development to, well,
| _develop_! Not side-by-side with your code, but in your code
| as well, at a fine-enough grained level.
|
| Common Lisp was _designed_ to be both interactive and
| incremental. It 's not a bolt-on feature.
|
| Jupyter notebooks and auto-reloading have a very different
| feel, and (dis)incentivize different qualities and processes
| of development.
| vindarel wrote:
| This set of jupyter + autoreloads + editor features might get
| you close, but you won't be on par to CL's level. I'm
| thinking about CL's interactive debugger, and about language
| features that were thought with interactivity in mind. On an
| error, you get the interactive debugger, you can explore the
| stack frames and get to the erroneous function, change it,
| recompile it, come back to the debugger and ask it to resume
| progress from this point, and see execution pass. You didn't
| have to re-run the whole operation. If we can do that in
| Python, I've been in my cave for too long^^ As such, this is
| how debugging a complex program looks like in Python vs in
| CL: https://lisp-journey.gitlab.io/images/debugging-python-
| VS-li... (Ravenpack [1] is a company that does big data
| analysis and that uses CL, they gave some talks, maybe you'll
| find more practical reasons from them)
|
| for the second point:
| https://mikelevins.github.io/posts/2020-12-18-repl-driven/
|
| There might be more CL libraries than you think:
| https://github.com/CodyReichert/awesome-cl but I'm not that a
| zealot to say you can ignore Python's ecosystem, especially
| in certain areas...
|
| [1]: https://www.ravenpack.com/
| throw10920 wrote:
| In addition to the comprehensive answers of reikonomusha and
| vindarel, I'll give you some specific things you can't do:
|
| Jupyter notebook: you can't run it as normal code - that is,
| you can't import your notebook from another file. You also
| can't evaluate arbitrary regions of the notebook (it's cells,
| the whole thing, or nothing), or nested sub-expressions. You
| can't evaluate code in parallel - if you have a cell calling
| a function foo() in a loop, and you try to redefine foo() in
| another cell - impossible in Juypter, trivial in CL.
|
| iPython + autoreload: you also can't redefine a foo() in a
| file when it's being called in a loop, docs state "reloads
| modules automatically before entering the execution of code
| typed at the IPython prompt". You don't get any sort of
| interactive debug-and-fix-up when you encounter an error. And
| so on.
| breuleux wrote:
| For the record, I have written a reloading library for
| Python called jurigged[0] that works on normal Python code
| and can indeed replace foo() when it's being called in a
| loop. There is also a way to do debug-and-fix-up, but only
| if you specify restart points in advance, unfortunately.
|
| It is probably still a good deal more limited to what can
| be done with CL, there are no miracles here, just saying
| the gap may not be that big.
|
| [0] https://github.com/breuleux/jurigged
| omaranto wrote:
| I don't think it's fair that you got down-voted for not
| knowing what Lisp-style interactive development offers beyond
| what ipython or jupyter offers. Many people don't know either
| and the proper response would be to explain, not to down-
| vote.
|
| EDIT: I was made aware of the guidelines to not comment on
| voting, I apologize.
| throw10920 wrote:
| > Please don't comment about the voting on comments. It
| never does any good, and it makes boring reading.
|
| From the HN guidelines at
| https://news.ycombinator.com/newsguidelines.html
| [deleted]
| peatmoss wrote:
| Hy is cool because it allows people to explore some lisp
| concepts in context of libraries they may already be familiar
| with. And Python has an enviable set of batteries. But compared
| to CL or Racket, Python's performance is a bitter pill to
| swallow.
| Kodiologist wrote:
| Even with PyPy, or Python libraries that are themselves
| written in C?
| mrtranscendence wrote:
| PyPy won't be a candidate in some scenarios (nor is it
| always _that_ much faster), and even libraries written in C
| leave some performance on the table when Python is the glue
| language. Don 't get me wrong, I'm hardly ever in a
| position where Python limits me from a performance
| perspective ... there's always Cython. But it could be
| better.
| masklinn wrote:
| There's also a new kind on the block with mypyc, though
| it's pretty much pre-alpha and I assume it comes with a
| very long list of limitations.
| adenozine wrote:
| There's also https://github.com/basilisp-lang/basilisp
|
| If you desire a path closer to clojure
| chrisrink10 wrote:
| Hey! I'm the author of Basilisp. Thanks for the mention here!
|
| Basilisp is much less mature than Hy but tries to stay
| generally compatible with Clojure, which is somewhat different
| than the goals of the Hy project.
| Kodiologist wrote:
| Cool, I'm a Hy guy; glad to meet you. Hy in its early years
| imitated Clojure syntax much more closely, and Clojure
| compatibility may've been implicitly a goal even if it never
| got to the point of cross-testing. These days we prefer to
| think of Clojure as one of several possible influences.
| chrisrink10 wrote:
| natrys wrote:
| This encouraged me to go back and get a two year old small
| project up to scratch with current Hy:
|
| https://github.com/natrys/ghdl
|
| I definitely had fun writing that in Emacs/hy-mode. And indeed
| having access to Python ecosystem is neat. However, if I may:
|
| - I didn't get to use any intellisense, which was quite painful.
| Is there any Language Server for Hy now?
|
| - I think Hy tends to break with every Python minor release,
| which is a bit annoying. Stable is still broken on 3.10, and
| alpha is a big change.
|
| - This one might be a matter of subjectivity but I felt that Hy
| is trying to be more "pythonic" and less "lispy", and I am not
| sure what to feel about that. For example, familiar things like
| `&kwargs` or `&optional` seems to have got replaced with
| something less familiar (particularly, change to `#**` for
| keyword arguments spurred this though).
| Kodiologist wrote:
| 1. Nope, sorry.
|
| 2. That's right. Hy depends much more on finicky details of
| Python than most Python packages do, particularly Python's AST,
| so each 3.x release of Python usually requires some changes to
| Hy to support it. Each Hy release supports (at least) all
| versions of Python 3.x that have been fully released and are
| not yet at end of life.
|
| 3. More precisely, we're trying to take more of our conventions
| from Python rather than Clojure. See
| https://news.ycombinator.com/item?id=31250992
| gilch wrote:
| Not Intellisense, but there is jedhy:
| https://github.com/ekaschalk/jedhy which can do completions.
| Last Hy version verified working for: Hy 0.16.0
| gilch wrote:
| Hissp is an alternative approach. Unlike Hy, which compiles to
| Python AST, Hissp compiles to Python, so it doesn't break with
| every Python release.
|
| Its read language (Lissp) doesn't have an Emacs mode (yet), but
| its syntax is so close to traditional Lisps that lisp-mode
| pretty much works. No completions either. There is Lily
| https://github.com/mjobuda/damascus-tools/tree/main/lily, which
| proved Jedi works on Lissp, but it's never quite worked right.
|
| Hissp leans more Lispy than Pythonic compared to Hy, but still
| prioritizes interop, so the object model is still Python's.
| potta_coffee wrote:
| I haven't used Hy for anything serious but I've poked around with
| it before and it's loads of fun.
| jhbadger wrote:
| Have they ever fixed the problem with let not being implemented
| (which was the case when I looked at it a couple of years ago).
| Lisp-like languages without let lose a lot of the inherent power
| of lisps.
| EnderShadow8 wrote:
| This might be interesting https://pypi.org/project/scoping/
| Kodiologist wrote:
| It's been implemented, found to be subtly broken, and re-
| implemented a number of times. Ultimately trying to impose a
| different model of scoping on top of Python's scoping is living
| in a state of sin; thus the difficulties. The status quo is an
| apparently working `let` due to a truly heroic effort by Sunjay
| Cauligi ( https://github.com/hylang/hy/pull/2125 ). You're
| encouraged to try to find bugs in it.
|
| In truth, I've never understood the fuss about `let`. It's
| taken a huge amount of Hy development effort, but it adds very
| little. Python's native scoping works well in the large
| majority of cases, and in tricky cases, I'd rather use
| `nonlocal` or `global` explicitly so I'm sure what's happening
| at the level of Python semantics. I suspect that people who
| heard that previous versions of Hy were missing `let` assumed
| that some other feature (such as nested lexical scopes) was
| also missing that has actually always been there.
| contravariant wrote:
| What problems did you encoutner implementing 'let'? Shouldn't
| it be equivalent to lambda expressions somehow?
| Kodiologist wrote:
| In some other Lisps, yes, but Python has its own idea of
| how function scoping works that generally isn't what you'd
| want with `let`. For example, in (let [a
| 1] (defn foo [] (setv a 2))
| (foo) (print a))
|
| you probably `2` to be printed, but the seeming equivalent
| Python code a = 1 def foo():
| a = 2 foo() print(a)
|
| prints `1`. Python interprets the assignment as declaring a
| new local variable. Frankly, Python got scoping wrong (in
| its quest to eliminate declarations), but here we are. So
| `let` needs to work around this somehow. The current
| implementation implicitly adds `global a` or `nonlocal a`
| as appropriate. (Actually, the name `a` is also mangled so
| that any references to `a` outside the `let` refer to a
| different variable.)
| m45t3r wrote:
| For me the example printing `1` makes sense because I
| think `let` as being something immutable, so I wouldn't
| expect `setv` to mutate that variable (would expect
| either a compiler error or the introduction of a new
| local variable).
|
| But maybe it is because I am familiar with Clojure (where
| `setv` or equivalents doesn't exist) and not other Lisps.
|
| This would be the equivalent Clojure code anyway:
| user=> (let [a 1] (defn foo [] (def a 2)) (foo) (println
| a)) 1 nil
|
| So yeah, makes sense for me. But can understand why some
| other people would expect the other way though.
| gilch wrote:
| Equivalent in Common Lisp: * (let ((a
| 1)) (defun foo () (setq a 2))
| (foo) (print a)) 2 2
| ashtonbaker wrote:
| this made me wonder - I know I can use global variables
| inside a function definition: a = 1
| def foo(): x = a foo()
|
| so if this 'a' is a new variable, what happens when the
| name collides with a global variable? a
| = 1 def foo(): a = a foo()
| > UnboundLocalError: local variable 'a' referenced before
| assignment
|
| yuck!
| all2 wrote:
| I'm not sure this is so much of a problem? Changing what
| you name the variable fixes the issue.
|
| Python is generally quite good at having a verbose option
| to express things, so I'm surprised there's not an
| explicit way to reference the enclosing scope from an
| object.
| vegai_ wrote:
| Is there any non-horror piece of code where supporting
| this latter case would be useful?
| m55au wrote:
| It is not a particularly good example. A better one would
| be a = 1 def foo(): x
| = a a = 2 foo() >
| UnboundLocalError: local variable 'a' referenced before
| assignment
|
| Basically a name cannot be both global and local inside
| the same function. Otherwise it would be a total mess.
|
| "a = a" just means assign the value of local variable "a"
| to a local variable "a", so the error makes sense.
| gilch wrote:
| It works if you disambiguate your namespaces:
| >>> a = 1 >>> def foo(): ... a =
| globals()['a'] ... print(a) ...
| >>> foo() 1
|
| Still yuck?
| baq wrote:
| it kinda sorta works when wrapped in a function
| def f(): a = 1 def g():
| nonlocal a a = 2 g()
| print(a)
|
| though nonlocal can't be used when referring to global
| variables... it's kinda bad.
| gilch wrote:
| You can still use `global` though.
| vaylian wrote:
| > In truth, I've never understood the fuss about `let`. It's
| taken a huge amount of Hy development effort, but it adds
| very little
|
| My use case is Jupyter notebooks. With normal Python scoping
| you quickly accumulate a lot of global variables and you
| might accidentally use the wrong one. With let-bindings you
| have variables that clean up after themselves.
| Kodiologist wrote:
| I'm not familiar with Jupyter internals, but I think
| functions would work well for this. Hy allows multi-
| statement anonymous functions, and you can do stuff like
| `((fn [] ... ))` to define and immediately call the
| function. One advantage of this over `let` is that it
| allows old locals to be garbage-collected. If memory isn't
| an issue, though, `let` should work well.
| mark_l_watson wrote:
| They are working on improving it. I wrote a short little book
| on Hy and I initially used the "let" macro. I stopped using it
| because in general Hy code can be automatically translated to
| very readable Python code, but using the "let" macro generates
| ugly Python code.
| rcarmo wrote:
| It's sort of back, implemented as a macro. I've yet to go back
| to Hy (I left because of the removal of let, plus other things
| I found missing), but I try it every now and then and the last
| time I did the namespacing was still a tad weird.
| gilch wrote:
| Have you tried Hissp yet?
___________________________________________________________________
(page generated 2022-05-03 23:01 UTC)