Part of it is that it compiles to Python bytecode, and took the simplest route of adopting Python's not at all lisplike scope. With `let`, you have a visual clue of variable scope; Hy had a broken `let`, and then got rid of it completely. Now it looks like there's a new `let` that might make more sense. I haven't used it in a couple years.
I've seen others make the same claim. How's the difference difficult to get. It might not be 100% clear-cut and have some edge cases, but in common parlance:
Compile -> compiles to executable machine code (or executable bytecode for your VM).
Transpile -> produces code in another language (which is then compiled or interpreted or whatever).
return/if/while/break/continue actually work in Hylang. Common Lisp doesn't have these. Scheme purists won't let you have them. Clojure obviously doesn't have them.
Let that sink in.
The fight against imperative programming has come so far that we banned not just goto but every commonly used control flow primitive. We have banned global variables too and FP purists want to go even further and remove the assignment operator. What is a monad exactly if not the ";" ? What is the end result except more confusing code ?
What does Hylang do ? It translates almost 1-1 the features of Python onto itself and its a transpiler if I am not mistaken. So you get all the features and libraries of Python without much fanfare. This is such a good idea that we need a C++ version of Hylang.
Now if we could get rid of the parens and have begin and end or something like "if .. fi" like civilised folks, that would just be perfect.
It has all of them!
CL-USER> (defun foo () (return-from foo 1) 2)
CL-USER> (if t 1 2)
CL-USER> (if nil 1 2)
CL-USER> (let ((x t))
(loop for j from 1 to 10
do (when (= j 3)
(setf x nil))
→ (1 2 3)
CL-USER> (loop for i from 1 to 10 do (format t "~&i: ~a~%" i) when (> i 4) do (return) do (format t "~& -~%"))
CL-USER> (do ((i 1 (1+ i)))
((> i 10))
(format t "~&i: ~a~%" i)
(when (= i 4) (go end))
(format t "~& -~%")
Hylang doesn't have goto, as Python doesn't have it.
Well you can always implement a goto by having
1. A list made of lambdas. List gives numeric addresses. Dict will give you named addresses.
2. Pass the above list itself to each of the lambda or make it a global variable called ADDRESSES.
No one talks about the cool imperative features of Common Lisp right ? The was the point I was trying to make.
Scripting is imperative.
Python is a scripting language .. right ? That makes Hylang a scripting language too. Hylang is (Python).
How did people learn sh, perl, ruby, python ? By writing dumb imperative scripts of course! Why the shame ?
Even from a cursory glance Hylang has more libraries than all the lisps combined. FACT. I think it fits perfectly for scripting tasks and for a change its easier for beginners to get started with. ipdb works with hylang folks!
I had to google it. Remember Liskell ? The Lisp that mapped onto Haskell ? I think Hylang and Sibilant should be treated as minimal lisps along the same lines. As compared to Common Lisp .. Hylang is worse and that can only be a good thing.
Not really. We have not banned them from anywhere, except where they were not part of the culture (e.g. Scheme -- and even there you can use them trivially).
Almost all working professional programmers (say, 99% of them, aside a statistically insignificant percentage working professionally with Haskell and Lisp and F# and so on) use for, while, if, exceptions, and so on. Hardly "banned".
>We have banned global variables too
And for good reason.
>and FP purists want to go even further and remove the assignment operator
Your initial data and constants need to come from somewhere, so nobody bans the assignment operator. But if you can avoid mutations, sure.
>What is the end result except more confusing code ?
Clearer code that you didn't took any time to study the concepts of to understand?
Having to know fewer concepts to use a language is not the same thing as the code being easier to understand.
A language with fewer concepts can lead to weak expressibility, so you need to e.g. write 100 lines to do what another does in 5, and with their intention more explicit in the code.
For an extreme example, consider how easy it is to understand a piece of code doing the same thing in assembly and in C. The C code will be much easier to follow, despite requiring you to learn more language constructs.
And inversely, a BASIC programmer could say the same things you said, but about, say, Python: "Why do we need all those language features, aren't line numbers and GOTO simpler?"
If learning 5 new concepts makes it possible to handle the same functionality in half the code, understand old codebases better, and write the same thing with less bugs, then those 5 concepts lead to simpler code -- even if they add to what someone already knows.
>What is a monad exactly if not the ";"?
Tons of other things.
Don't know where you get your facts from, but Common Lisp certainly has those.
(for [element (range 1 10)]
(if (= element 5)
CL-USER 51 > (loop for element from 1 upto 10 do
(if (= element 5)
I definitely made a stupid mistake of clubbing CL with scheme and clojure but in those languages they avoid these imperative features.
I have made other points as well which makes Hylang different from the rest.
1. Hylang is a transpiler. Don't compare it with other lisps. Sibilant and Liskell are others in the same league.
2. Hylang has more useful libraries than all the other lisps.
3. Right now, I find Hylang best suited to write good old imperative dirty scripts that get stuff done. If you have used Python, Ruby, Perl ... it's practically heaven.
4. I stress the imperative part again because ... because that's my stupidity of choice. I'm a scripting guy! I'm familiar with that stuff. The best part of lisp for me is not the macros. It's that I don't have to google for syntax that often and "-" beats the "_" for variable names.
5. ipdb works too!
But you are aware that the FOR loop code you posted looks almost exactly like the LOOP FOR code in Common Lisp?
Common Lisp does have them, as does. Scheme purists will let you have pretty much whatever imperative control structures you like (that's what macros are for), but you would be right if you said that none of the Scheme standards mandate simple equivalents for all of those (though since Scheme looping is usually recursive—which is perfectly imperative—“break” is usually just not recursing.)
> The fight against imperative programming has come so far that we banned not just goto but every commonly used control flow primitive.
Well, they weren't banned, Hough of course you won't find them in pure functional languages like Haskell. But CL and Scheme and Lisp-family languages with strong roots in those have robust imperative controlled structures and the foundations for building more if you need them.
It has been said that Haskell is the world's best imperative programming language: https://stackoverflow.com/questions/6622524/why-is-haskell-s...
For when you really need it, you could just use a block in CL and emulate it using return-from. Return and break are really the same thing, and don't really need to be separate.
CL is really an imperative language as well, it is just that it doesn't force you to be imperative to return things from an if or such things.
Scheme is a different beast. Since it provides you with the mother of all control structures (call/cc or prompts in guile/racket) mutability isn't really good if you want safety.
A quick perusal of hylang.org didn't reveal how a Lisp works without cdr. I'm envisioning something awful with a colon...