Hey everybody. Submitting this language because I really enjoyed using it lately. I like the clean look of my scripts after using it :), and it seems more than powerful enough to do some really awesome work.
I wrote a simple URL list processor recently, using curl and some other tools for status code and other check-ins, and the docs made it a piece of cake.
It's also cross-platform but I'm just using it in Linux for now. So if anybody is looking for a simpler or cleaner way to script, or just something new to try, I would offer ABS as a really nice experience so far.
Very few languages "grab" me as a "I need to try this" type thing, but this one has. I do A LOT of bash shell scripting; I may try this (and/or the NGS also listed in comments) for a few things.
Hello. Author of Next Generation Shell [1] here. I've skimmed ABS documentation and was surprised by the amount of similarities in thinking and reasoning between ABS and Next Generation Shell. Differences that popped into my head in limited amount of time follow:
* ABS has CLI and NGS does not yet, CLI of NGS will be written in NGS itself, so it takes time. The CLI in NGS will be radically different [3].
* ABS runs on Windows.
* ABS has decorators, NGS does not yet, still thinking how to do it right and more generic.
* ABS has some functions that NGS doesn't and vice versa.
* Found inconsistently named functions in ABS (json() vs tsv() - json() parses JSON while tsv() generates tsv); given more eyeballs on NGS, such inconsistencies should come up.
* NGS has user defined types.
* NGS has many predefined types, ABS has few.
* NGS has multi-methods and multiple dispatch.
* NGS has exceptions.
* NGS has (partial but already very usable implementation of) Universal Pattern Matching [2]
Translating example in the docs:
# ABS
res = `curl -s 'https://api.ipify.org?format=json'`
if !res.ok {
exit(1, "An error occurred: %s".fmt(res))
}
ip = res.json().ip
total = ip.split(".").map(int).sum()
if total > 100 {
echo("The sum of [$ip] is a large number, $total.")
}
# NGS
ip = ``curl -s 'https://api.ipify.org?format=json'``.ip
total = ip.split('.').map(Int).sum()
if total > 100 {
echo("The sum of [$ip] is a large number, $total.")
}
In NGS the double backtick syntax above runs external program and parses the output. The check of `ok` is not needed because on error exception will be thrown.
Author of another shell here. My syntax started out very similar to both ABS and NGS too but I found it cumbersome writing commands in C-style (strings quoted, parameters braced and comma delimited) for day to day CLI work. So I dropped the requirement for braces, then quotation marks, then commas. And before you knew it, you ended up with something that looked a little like Bash again.
There's obviously going to be a lot of subjectiveness around the design of shell languages but I've found this is one domain where a certain amount of ugliness is overall better than going for syntax purity because the majority of time you're writing shell code it's in a REPL, it's repetitive, and often it's because you're already trying to optimise on developer effort (otherwise you'd have written the thing in Go/Java/Python/whatever anyway). And while C-style syntax does offer some familiarity for developers that can help with readability, their primary function is really to provide hints to the compiler rather than aid development.
So ~7 years ago my shell went from looking a lot like yours, with the same methods and syntax, to fewer namespaces and more Bash-isms but using C-style braces only sparingly (eg to clearly denote different scopes of code).
To illustrate this, your same code for my shell would look something like the following:
trypipe {
get https://api.ipify.org?format=json | [body] | set resp
let total=0
$resp[ip] | jsplit: '\.' | foreach i { let total=$total+$i }
if { = total > 100 } {
echo "The sum of [$resp[ip]] is a large number, $total."
}
}
(I don't have a `sum` method so there is some ugliness there. But that's a pretty simple language addition should people want it.)
Your code is definitely more readable to your average developer. But the real question is how does it fair in an interactive shell? That, for me, is the real make or break of all these new alternative shell languages that are cropping up these days (and where I've focused most of my effort) because we already have plenty of write once read many languages. Where the industry is lacking is good write many read once languages.
Don't get me wrong, I think it's fantastic the work you're doing. This isn't a criticism in any way! More general curiosity how you guys have approached the interactive shell problem with a bit of back story about the journey I took when following a similar path as yourselves.
BTW if we remove error handling, I think ABS' code would look like:
ip = `curl -s 'https://api.ipify.org?format=json'`.json().ip
total = ip.split('.').map(int).sum()
if total > 100 {
echo("The sum of [$ip] is a large number, $total.")
}
I would suggest implementing decorators in NGS. Not because you will need them, but because they're easily the most fun part I had to write in ABS :) That, and seeing stdin() working for the first time on my terminal!
The page mentions Ruby, Python, and JavaScript as things they borrowed from. I see a fair amount of what looks like Perl inspiration though. Maybe indirect via Ruby, I guess.
How do you get things like nulls or arbitrary bytes into a string? The string literal format seems to only understand \r and \n and \t. Nothing like \xff or \0, for example. And I don't see ord(), chr() or similar.
I just wanted to say thanks for sharing this, it made my day. I started ABS a couple Christmases ago as I had a week off and the constant thought that there's gotta be a "nicer" way to script things, without the verbosity of higher-level languages...and I'm happy to see folks finding ABS useful.
I haven't updated it in a couple of months as I find it pretty "complete" from my perspective, but I also have some crazy ideas every now and then that I know I'll want to throw into the language.
Again, thanks for giving ABS a try!
PS. I wanted to credit Thorsten Ball for his books, without them I would have never been able to build ABS:
Hi - glad to see you here. I just posted a comment about the sample code on the home page - your comment wasn't up when I started writing it or I might have replied here.
Yes, I replied to your original comment. Again, truth to be told I've got limited space to work with on the UI to showcase some of the syntax but I agree that snippet doesn't make a lot of sense...suggestions welcome!
Hmm. The first sample code on the home page looks a bit odd - can we really create arrays with an unspecified number of entries and fill in every other entry?
obj = {}
for n in 1..10 {
if n % 2 == 0 {
obj[n] = rand(10\*2)
}
}
echo("We have %s", obj)
# {"10": 79, ...}
Let's try it. Copy the source code into the playground. Nope! Error. Try downloading and running again. Nope! Same error.
Hmm. Let's see if we can fix it. What are {} anyway? Oh! Hashes!! Can we really create hashes without.. wait, wait wait. The program is not accessing hashes, it's treating obj like an array. OK. Let's change the {} to [].
Oh joy! It runs! Interesting, the output is "We have [null, null, 51, null, 50, null, 51, null, 86, null, 64]".
Based on the comment in the last line of code, that's not the expected output.
So maybe the %s isn't working? Also, there are 11 elements in the output. Why write "n in 1..10" to create 11 elements? Also, the first value in the result is null; the sample comment suggested it was expecting some kind of value.
My conclusions:
1) It's not clear what the sample code is trying to do.
2) There are at least 2 things wrong with the sample code, at least in terms of some kind of simple way to show off: doesn't run (wrong syntax) and doesn't provide expected output (comment). I am guessing syntax has changed and they didn't update the sample code.
3) The sample code seems to imply 1 based array indexing, but, according to the docs, abs apparantly uses 0 based array indexing.
4) Given the above is the first example sample code on the home page, it is hard to imagine this programming language is stable enough or otherwise optimized for a good onboarding experience.
On the other hand, it appears that yes, we can really create arrays with an unspecified number of entries and fill in every other entry without manually adding array elements.
Sorry the example on the docs is definitely not a good one, though I've had a hard time finding something more appropriate that can fit within that block :) Suggestions are more than welcome!
Hash keys need to be string (eg. n -> n.str()), I fixed the example on the homepage.
>can we really create arrays with an unspecified number of entries and fill in every other entry
Seems that was a typo, but you can do that in some languages, either directly (Perl, PHP) or with help (many others). "Autovivification" seems to be the term:
23 comments
[ 5.6 ms ] story [ 70.3 ms ] threadI wrote a simple URL list processor recently, using curl and some other tools for status code and other check-ins, and the docs made it a piece of cake.
It's also cross-platform but I'm just using it in Linux for now. So if anybody is looking for a simpler or cleaner way to script, or just something new to try, I would offer ABS as a really nice experience so far.
https://apps.apple.com/us/app/dinar-guru-top-dinar-recaps/id...
* ABS has CLI and NGS does not yet, CLI of NGS will be written in NGS itself, so it takes time. The CLI in NGS will be radically different [3].
* ABS runs on Windows.
* ABS has decorators, NGS does not yet, still thinking how to do it right and more generic.
* ABS has some functions that NGS doesn't and vice versa.
* Found inconsistently named functions in ABS (json() vs tsv() - json() parses JSON while tsv() generates tsv); given more eyeballs on NGS, such inconsistencies should come up.
* NGS has user defined types.
* NGS has many predefined types, ABS has few.
* NGS has multi-methods and multiple dispatch.
* NGS has exceptions.
* NGS has (partial but already very usable implementation of) Universal Pattern Matching [2]
Translating example in the docs:
In NGS the double backtick syntax above runs external program and parses the output. The check of `ok` is not needed because on error exception will be thrown.[1] https://github.com/ngs-lang/ngs
[2] https://github.com/ngs-lang/ngs/wiki/UPM-Design
[3] https://github.com/ngs-lang/ngs/wiki/UI-Design
There's obviously going to be a lot of subjectiveness around the design of shell languages but I've found this is one domain where a certain amount of ugliness is overall better than going for syntax purity because the majority of time you're writing shell code it's in a REPL, it's repetitive, and often it's because you're already trying to optimise on developer effort (otherwise you'd have written the thing in Go/Java/Python/whatever anyway). And while C-style syntax does offer some familiarity for developers that can help with readability, their primary function is really to provide hints to the compiler rather than aid development.
So ~7 years ago my shell went from looking a lot like yours, with the same methods and syntax, to fewer namespaces and more Bash-isms but using C-style braces only sparingly (eg to clearly denote different scopes of code).
To illustrate this, your same code for my shell would look something like the following:
(I don't have a `sum` method so there is some ugliness there. But that's a pretty simple language addition should people want it.)Your code is definitely more readable to your average developer. But the real question is how does it fair in an interactive shell? That, for me, is the real make or break of all these new alternative shell languages that are cropping up these days (and where I've focused most of my effort) because we already have plenty of write once read many languages. Where the industry is lacking is good write many read once languages.
Don't get me wrong, I think it's fantastic the work you're doing. This isn't a criticism in any way! More general curiosity how you guys have approached the interactive shell problem with a bit of back story about the journey I took when following a similar path as yourselves.
In NGS, there are two syntaxes: "commands" and "expressions".
Commands is bash-like. It's for running external programs.
Need some fancy stuff? Switch to expressions and pay the price.
I didn't see (and still don't see) any way to make a "real" programming language based on bash-like syntax.
What happens in ABS if curl fails in this example? Or JSON parsing fails? In NGS, it's an exception with a stack trace.
> fun part
NGS is mostly use-cases oriented - https://github.com/ngs-lang/ngs/wiki/Use-Cases
Decorators are not implemented yet because there are other things higher up the list. Currently working on deeply nested data structures because it's needed for our use case for FHIR - https://github.com/ngs-lang/ngs/wiki/Deep-Data-Structures-Ma...
Too bad
https://github.com/abs-lang/abs/issues/447
Feel free :)
- A convenient excuse to sit and think for a while
- Associated with taking a little break from life's higher-minded ideals and demands
- Mostly rooted in the same environs; doesn't change a lot
- Stinky sometimes, but shiny and edifice-like when given attention [0]
- Underappreciated in its utility and support for common tasks
OK, I'll wait for that one too. :-)
0. https://www.youtube.com/watch?v=qqg4rJPUxGs
I just wanted to say thanks for sharing this, it made my day. I started ABS a couple Christmases ago as I had a week off and the constant thought that there's gotta be a "nicer" way to script things, without the verbosity of higher-level languages...and I'm happy to see folks finding ABS useful.
I haven't updated it in a couple of months as I find it pretty "complete" from my perspective, but I also have some crazy ideas every now and then that I know I'll want to throw into the language.
Again, thanks for giving ABS a try!
PS. I wanted to credit Thorsten Ball for his books, without them I would have never been able to build ABS:
https://interpreterbook.com/
Does the sample code need updating?
Hmm. Let's see if we can fix it. What are {} anyway? Oh! Hashes!! Can we really create hashes without.. wait, wait wait. The program is not accessing hashes, it's treating obj like an array. OK. Let's change the {} to [].
Oh joy! It runs! Interesting, the output is "We have [null, null, 51, null, 50, null, 51, null, 86, null, 64]".
Based on the comment in the last line of code, that's not the expected output.
So maybe the %s isn't working? Also, there are 11 elements in the output. Why write "n in 1..10" to create 11 elements? Also, the first value in the result is null; the sample comment suggested it was expecting some kind of value.
My conclusions:
1) It's not clear what the sample code is trying to do.
2) There are at least 2 things wrong with the sample code, at least in terms of some kind of simple way to show off: doesn't run (wrong syntax) and doesn't provide expected output (comment). I am guessing syntax has changed and they didn't update the sample code.
3) The sample code seems to imply 1 based array indexing, but, according to the docs, abs apparantly uses 0 based array indexing.
4) Given the above is the first example sample code on the home page, it is hard to imagine this programming language is stable enough or otherwise optimized for a good onboarding experience.
On the other hand, it appears that yes, we can really create arrays with an unspecified number of entries and fill in every other entry without manually adding array elements.
Hash keys need to be string (eg. n -> n.str()), I fixed the example on the homepage.
Seems that was a typo, but you can do that in some languages, either directly (Perl, PHP) or with help (many others). "Autovivification" seems to be the term:
https://en.wikipedia.org/wiki/Autovivification