I don't know about quirky, back when I first found out about it, it was surprising that I could read it without having written a single line of code on it. That's damn impressive.
To me, its type system and parsing nature are one of a kind, to be able to label everything as what it is
[money!] is $12.53
[tuple!] is 5.5.5.5
[date!] is 16-Jul-2023/21:00:17
means the parser immediately parses and type checks everything, all while looking as human readable as possible.
been a while since I played with Red, but from what I remember the problem was this:
1. default compile mode was shared, so all executables relied on a "libred.dll" or similar
2. compiling "libred" was really slow (1 minute), but after that its done and skipped in the compile stage, making compile much faster (but still with the limitation of #1)
3. you can compile static, but then the static "libred" needs to be compiled EVERY TIME, making every single static compile, even "hello world" take one minute EVERY TIME.
I posted multiple issues about #3, but they were closed each time as "wont fix" or "working as intended" or similar. So OK fine, I just moved onto Go and Rust, even C, plenty of other languages that dont have this issue.
yes, that was one of the arguments. however I dont accept that. I have used C, C++, C#, Crystal, D, Go, Nim, Rust and Zig, none of which have this issue.
But do those languages permit rapid Lisp-like development in the way Red does? I am not sure I see the problem. The slow static compilation is reserved for the final deployment of the app, so it should not hinder development.
> yes, that was one of the arguments. however I dont accept that. I have used C, C++, C#, Crystal, D, Go, Nim, Rust and Zig, none of which have this issue.
Which issue? This one?
>>> but from what I remember the problem was this:
>>> 1. default compile mode was shared, so all executables relied on a "libred.dll" or similar
Don't all the above languages, besides Go, rely on a library for runtime? Ever got the error `missing msvcrt110.dll` when distributing binaries of your application on Windows?
The only difference here that I see is that you can choose to recompile the runtime; with C, C++, et all on Windows, you don't get that choice - you have to use the dlls that the language specifies whether you like it or not.
You shouldn't need to recompile the runtime to statically link it.
Red might not have a way to store intermediate static linking files and so is forced to do a full compilation everytime.
Caching at the output file level is simplest but can result in these kinds of weird performance issues.
(Shipping a precompiled library is standard to avoid this pain point, MSVC includes four versions of its standard library, Debug/Release and Static/Dynamic in the various combinations)
No, at least C, C++, D, Rust and Zig allow static linking of the runtime libs, even on Windows. And they don't recompile it every time. Rust especially will static link everything by default.
That's not entirely correct. Rust on Linux will dynamically link glibc and libgcc by default. And you can't reliably create a fully statically linked executable on some operating systems like macOS et al.
While what you write is more or less true, the biggest problem here is that compilation is OPTIONAL. Red scripts can run in the interpreter just fine and TBH I use compile very rarely.
it's a dynamic language with optional compilation, so complaining that the compiler is slow isn't very fair.
The compiler is written in Rebol (language Red is based on) which is dynamic language also, so that's why it's slow. Rebol itself is written in C and its scripts can't be compiled. You can of course bundle the script with the interpreter which is ~1-2MB with OS dependencies only.
(I used to work for Red and use Rebol in my job daily)
Sounds like exactly the problem of Julia language. On the surface, Julia seems slick in code and fast in running. But then you discover that
1. there are no objects, so when you switch from Python, instead of chains of methods, like `my_dataframe.groupby(...).aggregate(...).groupby(...).aggregate(...)` you need either (a) a lot of poorly readable nested calls, or (b) ugly "pipes", where the left side is implicit first param of the function on the right side: ` my_df |> groupby(...) |> aggregate(...) |> groupby(...) |> aggregate(...)`. (Writing them, you feel insecure of what is happening -- in this case, what gets passed to the function.)
2. You can't make it a CLI script, because it compiles the whole code WITH dependencies every time, and as soon as you import some serious libraries, compile times will skyrocket. I quickly hit 40 seconds of compilation with just geospatial lib and dataframes. These 40 seconds turned out to be A LOT when you develop interactively. And you can't build everything in a Jupyter Notebook, because eventually you'll have to switch to a CLI script.
I think I could put up with pipes, but the compilation times were the final argument against Julia.
> (b) ugly "pipes", where the left side is implicit first param of the function on the right side: ` my_df |> groupby(...) |> aggregate(...) |> groupby(...) |> aggregate(...)`. (Writing them, you feel insecure of what is happening -- in this case, what gets passed to the function.)
These are not ugly pipes. These are a very common feature in a lot of functional languages. Once you've used them, you want them everywhere :)
And of course you know exactly what is passed to the function. You wrote it yourself: left side is passed as the first param of the function on the right side.
I think it's not so clear a lot of times which function is called. Say you write a function that accepts your type as an argument. Cool, you compile it everything is good. Now you import a library, just so happens it also has a function that has the same name, and accepts an argument of the same parent type. Which function gets called? If you're reading the code and not intimately familiar with how imports work, all the imports in scope, and the function your coworker defined on like 5,000 in a random file you might not be sure unless you start debugging.
Pipes are fine, but methods and traits with a strong type system reduce any ambiguity there.
Doesn't mean you can't use pipes reasonably! But in Julia that seems like it could be harder to unpack.
> Say you write a function that accepts your type as an argument. Cool, you compile it everything is good. Now you import a library, just so happens it also has a function that has the same name,
This has nothing to do with pipes, this is a matter of namespacing.
This is why I generally dislike imports. It's common practice in Elixir (and I believe some other functional languages) to generally fully qualify function calls.
I'm sure some will think that is too verbose but I love it. Otherwise pipes are far more flexible than method chaining just because you aren't constrained to one "type". You don't always want to do this, but as per the example above, it's pretty handy. You also don't have to rely on a method you don't own returning an instance of itself.
well, it depends on how import works. in python you can't use a module unless you import it, (though you can import it in a way that the full path to the function is still needed)
but for example in pike import is only useful as a shortcut, and not needed if you use fully qualified function calls. and like you i never saw the point of import. using the fully qualified function calls makes the code more readable because i can quickly recognize library functions from custom code.
True enough about Python but I was responding more about pipes in general which Python doesn't have. I'm more confused about the original assertion that pipes give you lower confidence as to what is happening. But then I looked up how they work in Julia and saw there are two different ways they are implemented so I agree that that is maybe a little bit unfortunate, though I can't really say for sure as I've never written a line of Julia.
i saw pipes and import as two unrelated topics, and i was just responding to import topic.
with pipes i have no experience at all. but they certainly look useful. a()|>b()|>c() looks better than c(b(a())) but i can see the confusion because there are now two ways to pass an argument. but even then a(i,j)|>b(x,y)|>c(z) is still more readable than c(b(a(i,j),x,y),z). now i want this feature in all my favorite languages
Ya, pipes are really nice. Of course people do tend to get obsessed with them and try and make everything a pipeline. I find pipes fit the functional paradigm really well as they are clearest when they don't result in any kind of side-effects or mutation. Method chaining, on the other hand, is all about side-effects (mutating the object).
I really like pipelines but know people who try and make everything a pipeline.
Not sure why I got down oted so hard but I personally like, x.a().b().c(). Because the functions are bound to the type. When they aren't sure pipes, but that's rare when a type is well defined. Super zen for me
if course x.a().b().c() is just fine, but it only works in object oriented languages where these functions return the right object for the next step. the pipe method works with any other function as long as the output type matches the type of the first argument of the next function.
ML languages aren't really OOP similarly neither is Rust really. There's a beautiful middle ground between piles of functions and types with purpose that doesn't suffer from the swamp nor the over abstracted mess that a lot of paradigms offer. Okay I'll get off my high horse but I recommend trying one of these paradigms someday if you haven't already. Traits are wonderful.
I can't explain the downvotes other than that in OO method chaining does not bind you to a specific type. I don't really know Python but in Ruby, for example, you can do `"string".split.map { |s| s.upcase }`. IE, a method doesn't have to return a reference to `self`, so I'm not really seeing your argument other than choosing to use the style of only chaining when the object types match, which you can still do with pipes if you want.
The only ML language I have any experience with is OCaml which is statically typed and has pipes.
EDIT: re-reading your last comment it looks like I totally ignored the first part of what you said, but I guess I'm confused. This thread is also probably nested enough, lol.
Just that you can do `|> foo()` implicitly into the first argument or, via another package mentioned in the official docs, `|> foo(_)`. This isn't necessarily a bad thing, I was just trying to understand the comment way up this thread that said: "Writing them, you feel insecure of what is happening" as that makes no sense to me.
Ah, okay. The use of the second form requires a `@chain` macro annotation in the beginning of that expression, so I've never found this to be ambiguous.
Ah. I see what you mean. I think this is the issue with the language and/or tooling. Most languages will not let you import a function from two different libraries under the same name, and most languages will warn you if you use a function with the wrong arity.
> methods and traits with a strong type system reduce any ambiguity there.
Pipe is useful, of course. I personally just dislike the symbols selected for it, they're harder to type.
And no, in many cases, it's absolutely not clear what gets passed, because you may have a vector of scalars, and the function accepts... what? Is it restricted in input types at all? If it takes a scalar and then gets passed a vec of them (but you don't call it's vectorized equivalent), what happens?
Yes, I can go check the function, check if I have a vec and check if I call the function the proper (scalar or vectored) way,.. but this escalates the complexity and choices you should make, towards Rust language. And still it can run and try doing something implicitly. When I coded it, I wasn't sure I can't mess things up somewhere in the middle of the pipe.
Don't get me wrong, I liked many features of Julia. I made one project in several languages just to compare, and Julia was easy to learn and worked pretty well. The main issue that stopped me from using it was the above mentioned cold start time.
i haven't used a lanuage with this feature before so i don't know anything, but i don't understand the problem. how is the return value before the pipe being the first argument any different than normally putting it into the argument list in the first position.
or is there an implementation where a pipe takes a vector and applies it to the next function as multiple arguments?
Dataframes are vectors of vectors. And functions on them may return either vec<scalar>, or vec<vec<scalar>>, and in a chain of such operations it's easy to lose track of what you have.
One of the reasons it's not so famous is that it's had various historical struggles, including being stuck at 32-bit for a long time IIRC (I'm hazy on the details and corrections welcome). I love it though.
Seems like the development is much more focussed since last year and a lot is happening with 1.0 (and 64-bit support) being on the way possibly by the end of this year. [1][2]
I am really looking forward to learn more about this language when 1.0 comes out, especially because of its ambitious feature list [3] (programming across the low/high-level spectrum, etc.), Lisp influences and the Logo-like syntax inherited from Rebol.
Also they went of down a cryptocurrency path for a while, not sure where that's at but it certainly seemed like a big distraction from finishing the main thing.
I have spent an entire day last week studying Rebol and was not able to find an active enough fork. The language has great ideas but by God, are they terrible at just letting their presence known, both the original product and this fork.
Call it the Rebol curse, I guess.
All I could find were 32-bit binaries on a couple sites compiled a decade ago, and a lot of focus on Red, which is in a weird limbo as well.
Red seems to have similar challenges. They have their code on GitHub, but the Releases are confusing. They have 3 releases posted. The latest one is 5 years old. But the project is active. You can download from their site, but the version number isn’t obvious.
From poking at the project, it looks interesting but not ready to really try out yet.
That is probably what I hate the most about today's technology.
"compiled a decade ago"
Listen here, kid. Two and a half decades ago I had Windows 95 and I could browse the Web, send and receive email (or fax!), play music, play videos (or movies), play games, use instant messaging, program in multiple languages, use databases, run a mail or Web server on my desktop, read and edit documents in formats such as doc, rtf, xls, ppt, pdf, xml, desktop publishing, view and edit images including high re photos, including porn of course, make international phone calls, and a few other things.
And every single Tcl/Tk script (cli or gui) I wrote two decades ago still run 100% unchanged.
If you refrain from using anything just because it was "compiled a decade ago" then you are a fool. Sadly, you are not alone. Far from it.
Weird take but ok. I abandoned my research into Rebol to look into Self (1987) and Smalltalk (1972).
The problem with abandonware languages like Rebol is that it's often impossible to use, find documentation for if not learn, and the commercial story and lack of any sense of open source of this probect is the reason why I just moved on. It seemed no one cared to look into it in the past decade, so I was content with what I had found, and stopped short of actually using the thing. I was wrong, but in my defence the active fork was doing its best to hide under a rock.
But I guess it feels good to call someone a kid and a fool over the Internet.
a lot has happened in the last 10 years. and while the binary may still be good, it being that old suggests that it is no longer maintained, and in particular hasn't received any security updates. that doesn't mean that a recent binary is necessarily better, but it is at least more likely to be better.
The creator, Carl Sassenrath, also wrote the pre-emptive multi-tasking Amiga OS. He was a fan of Lisp and Logo and wrote Amiga Logo after he left Commodore. Rebol is based on Logo and Lisp.
Rebol reminds me a lot of Tcl/Tk, but I can’t tell if that is because there’s a dialect that resembles it, or that it takes inspiration from tcl’s command substitution.
prin is an alternate spelling of preen. Okay so something about boldy wearing their feathers is a preen/to preen? Can anyone confirm?
Does not help in guessing what ``prin "helloworld"'' does.
Red is based on the Rebol language and is said to be 95% compatible with Rebol 2.7. The Red website includes links to the tutorials and code examples for Rebol alongside Red specific links.
Zig does have some memory safety, but not as much as Rust of course. I think Zig made the decision to add as much safety as they could, without crossing the complexity boundary. any further memory safety and you're about in Rust land. maybe some middle ground language is possible, but not one that I know of.
> any further memory safety and you're about in Rust land...
That's not quite true. We have GC using languages (some allow it to be turned off), and for many or in many use cases, that would be enough. Other languages like Lobster, Vlang, Vale, etc... are developing/putting out easier to use alternatives.
For me, Vale would need to be able to produce static executables the way Go does, without pulling in a kitchen sink of DNS and curl+dependencies type of libraries.
Easy != simple. I find it baffling how on one hand you like TypeScript for its "simplicity" while asking for a language with "the philosophy of zig in terms of simplicity".
TypeScript has more than enough complexity even without the npm ecosystem.
If instead of Rust you'd take its close enough relative, OCaml, but without the GC and with more low-level machine access, maybe ATS would fit your bill.
If they literally mean safety then perhaps Golang fits the bill but they said safety _like Rust_. They probably still want the control that Rust provides.
For sure, and I think different people may understate or overstate its complexity. It's definitely worse than Go but it's not nearly a field of landmines like C++. I think it's quite feasible to learn the basics in a short period of time, but maybe that's just me. I guess we'll see how Vale and the others turn out in production.
I get the practical reasons why it’s useful, but I’m surprised it’s anyone’s choice for the design of a high level language. Is Python or Ruby not a much better choice?
Python's biggest inherent issue is it lacked async syntax for a long time. Haven't used the newer versions that have it, so idk how well it works. JS also has a way better package system and nicer syntax for objects and lambdas. Then the more practical issue is all the UI stuff integrates with JS rather than Py, and Py is even slower than JS.
Ruby, idk, never used or even encountered it. Python was my main language for a while.
The syntax points are fair, but the lack of standard library in JS complicates so many things. I'd contest the idea that the JS package ecosystem is better – there is more tooling, but I'm not sure the tooling is better, and the average package quality is easily the lowest in any ecosystem I've worked in.
I could see fully modern JS, without any transpilers, being an ok scripting language, I guess that's why React Native works well in that way.
Seems like Python projects (e.g. the top Py-based Github repos) always have Dockerfiles because they know pip+venv or whatever is notoriously finicky, whereas JS projects will rely safely on npm which is quite portable. After fighting with my Python packages for so long, JS was refreshingly easy.
For standard library, NodeJS keeps things pretty simple server-side. It's messier client-side with browser standards, but it's getting better, and Python can't even run in-browser. I like how JS evolves more gradually than Py which had the hard 2->3 transition.
I was really hoping this was a 1.0 announcement but, I'll take what I can get.
Red is a really promising language. It, like Lisp, gets flak because of the syntax but that really becomes a non-issue pretty quickly once you start using it and the productivity gains you see from using it all but eliminate any reservations you might have about the syntax.
Never heard of it before, but I am a bit curious about it being homoiconic. I wonder how it comes into play in Red/Rebol world, a little more thorough. This page shows some examples of lisp-like 'apply: https://www.red-lang.org/. I wonder if the use of '[] is inspired by pre-modern lisp M-expressions (Mathematica is also using them), or is it for some other reason, like let's pretend we are not a lisp-like language so to not scare of folks? :) Square brackets and curly brackets are unfortunately harder to type on some layouts. On Swedish layout I have to press alt-gr to type those, while ordinary parenthesis are a bit simpler: I can use shift, which is found on both sides of the keyboard.
Perhaps such things sounds trivial, but in a language where they claim that programming should be fun, hard to type things are a bit of fun-killers. I also disslike both visually and if I would to type all those operators #,%,$,?,:,! etc. We humans are used to raede txet adn cna prase text even when mistyped without barely stopping, but the punctuation is a bit harder to read and type, and that for a reason. That becomes especially annoying if those signs are overloaded or combined, as in Perl or C++, which is probably one of the reasons that gives those languages "write-only" epithet.
I have seen the video: https://www.youtube.com/watch?v=-KqNO_sDqm4 by Nenad, but it is from 2015. If they are still 4x slower than C for the compiled code, than I am very hard to believe they are a serious contender to become a systems programming language as they claim to be. Compare to sbcl (Common Lisp) where speed is almost approaching C in some cases. Having built-in toolchains and DSLs is nice, but it can also be a curse and made things harder to evolve and modernize.
While I sound like a very negative person, I do like some of the ideas in Red definitely. Built-in tasks, concurrency and homoiconicity sounds like a very nice features to start with.
Red is mostly written in Rebol 2.7 whose final release was in 2011 when most software was 32-bit. Until Red becomes fully self-hosting, it looks like there will not be a 64-bit version.
FYI, the link from the first bullet point "human friendly syntax" (aka syntax) points to https://pointillistic.com/ren/ which is broken, returning a page that states:
Not Found
The requested URL was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
Why would fragmentation imply you can't have a GUI? You would just pick one toolkit and depend on it being there (unless you statically link it). Setting it up correctly is then the job of the user or distributors.
There is libgtk, aside from breaking changes between versions, some projects just don't want to "put up" with arbitrary decisions of upstream. Hence QT and KDE for example. But that has LGPL issue.
Until a major backer steps up and funds a project with amounts that is comparable to what MS or Apple spends on their GUI, the Linux on desktop is not happening.
Rebol had both (and more) decades ago, so it does seem odd to me Red doesn't given how much of it was inspired by that. IIRC its original concept was "open-source rebol".
It's original concept was not just "open source" (no hyphen required, nor is it "opensource" :), but to be a much better Rebol than Rebol - which itself was a neat concept and implementation by Carl Sassenrath, also creator of the Amiga OS.
I had used Rebol for writing small programs a while ago, and it was fun. The Rebol software was also very light, at under 1 MB, IIRC, for both the Windows and Linux versions.
Nice to see Red getting attention. I have been playing with Rebol a while ago and I really liked how easy it is to do program manipulation and writing small DSLs.
However, I found debugging to be very difficult, once I wrote a more complex application. Are there good debugging tools for Red?
Recently I had to target AIX and AS-400. Unfortunately I didn't even have a development environment for those projects, and cross-compiling wasn't available. So Java was pretty much the only option which let me keep my sanity. There just isn't anything like it.
A bit off-topic, but what's with all the 404 links in that about page? With all the missing pages it felt like a treasure hunt to find any information about what the language actually looks like. Literally the first four links in the About page are either broken or point to unrelated pages, so it took me five clicks to find the first example of the language.
I will take this opportunity to ask if someone can explain how Rebol/Red scoping works? I have read all the Bindology, etc. stuff and it's still not clear; I suspect it would be much easier to understand if someone could explain it in terms of how one would implement it in a interpreter (just like Dynamic scoping makes much more sense when explained that way).
Was the Red language / environment using a non-free license some time ago? I see now it's basically under BSD 3-clause license; am I mistaking it for something else?
It probably was Rebol that one. Rebol core is free and open source, the GUI distribution is instead released in binary form, as freeware (and exists only for rebol 2.7, we know about rebol3 only for Core).
BUT! There's an open source version of Rebol3 with GUI, from Atronix. I still don't know how the hell it works, like, what does it pull for dependencies.
that wasn't there when red started, and i don't know if it is a drop in replacement for the version red needs. if it isn't then they probably just didn't bother porting since they want to be selfhosting in the future anyways.
I wouldn't try building red from source with neither the official rebol 3 nor this Atronix release (nor Oldes fork, nor Ren-C), on their site they always built with rebol 2.7.
I thought red aimed for self-hosting, but as far as I can delve in their sites, I infer that they are rolling the rebol way and you "should just download the binary distribution". Meh!
well, that explains why they are not using this FOSS licensed rebol. it's the wrong version. they are aiming for self hosting, it's just taking them a while to get it done.
take a look at their roadmap:
*v0.7 : Full I/O with async support.
*v1.0b : (beta) completed self-hosted Red with 64-bit support.
For reaching the 1.0-beta milestone, we target 12 months of intensive work, so that will bring us to Q3 2023.
so that was written in june 2022 before 0.7.
there is no announcement for 0.7, but then they changed the versioning so i can't tell if the goals for that have been reached. but it's pretty clear that self-hosting is the next big target.
I had a brief interest in REBOL before Ruby, and definitely before I decided I never wanted to deal with a language with mutable data ever again if I could help it
I don't understand the appeal of these langs, I mean its fun as a hobby to develop but srsly who uses it? Unless you show me real stuff like loading an image and manipulating it or opening a file and parsing text for some pattern etc all the factorials won't cut it. The syntax looks real pain in the slot, worse than modern C++ but atleast the latter works like a charm and easy to understand if you cut the clutter.
More like Logo and Lisp. Of course, Logo is also a Lisp.
Red is based on Rebol, which was created by Carl Sassenrath, the creator of the pre-emptive multi-tasking Amiga OS. When he left Commodore, he wrote Amiga Logo and the created Rebol.
Whew. I’m glad this exists. It’s been a few days since yet another programming language has been introduced into the world.
Sarcasm aside, while I think striving to be better is great, sometimes I wish there was just a standard language for programming.
I realize it depends on the context (mobile, web, desktop application, different platforms) but it can feel overwhelming when in the end, they all pretty much do the same thing: tell a computer to do things.
Because the author and the team keep setting unachievable timeframes.
Five-ish years ago they were aiming for a 1.0 within a year while still having major milestones like adding actors (and re-writing half of internals to support actors) on the roadmap.
not new, and red is actually quite interesting compared to other languages, worth having a good look.
Also, worth reading Paul Grahams "Blub Paradox" article from decades ago... http://www.paulgraham.com/avg.html (hopefully you know who he is given you are here on HN)
> PL/I (Programming Language One) is a procedural, imperative computer programming language initially developed by IBM. The PL/1 ANSI standard, X3.53-1976, was published in 1976. It is designed for scientific, engineering, business and system programming.
> IBM wanted a single programming language for all users.
> The language is designed to be all things to all programmers.[vague]
https://learnxinyminutes.com/docs/red/
https://www.red-by-example.org/