User talk:T.J.S.1

From Esolang
Jump to navigation Jump to search
"Hello, T.J.S.1"
print

--(this comment by Koloneltedi at 09:55, 22 August 2013‎ UTC; please sign your comments with ~~~~)

 S S S	T	T S	T	T S S
L	T
L S S S S S	T	T S	T	T	T	T
L	T
L S S S S S	T	T S	T	T S S
L	T
L S S S S S	T S	T S
L	T
L S S
L
L
L

--(this comment by T.J.S.1 at 10:00, 22 August 2013‎ UTC; please sign your comments with ~~~~)

Regarding StackStack

Hey, Tom. I've very nearly finished my StackStack interpreter, and I've hit upon a few aspects of the language I'd like to discuss with you. Programming in this simplified Forth is already quite enjoyable (race you to the brainfuck interpreter!), but perhaps we might collaborate to make it that much better.

For starters, ASCII was first standardized more than half a century ago. Particularly given the simplicity of supporting it in JavaScript (fromCharCode() and charCodeAt() on String), I hope you'll agree that Unicode awareness ought to be part of StackStack's specification. That said, it's your language, so I understand if you have any reservations in this area.

Still on JavaScript, it would seem that you made the (perfectly reasonable) assumption that StackStack would never be implemented in any other language; I'm referring, of course, to the alert operation. It's admittedly unlikely to see too much use, but I wonder if you have any suggestions regarding how best to provide an acceptable facsimile from less graphically equipped languages.

I'm not done with JavaScript just yet. :P

As any sufficiently high-level language should, JS allows one to convert pretty much anything to a string; it seems thoroughly unnecessary to have to pass everything through the tostring operation before printing, when print could very well perform the operation silently on the programmer's behalf. The instruction does have its uses, certainly, but I don't think preparation for printing should be one of them. Again, how best to proceed is entirely your prerogative.

One last thing on dynamics: having both inputnum and inputstr seems overkill. My implementation does the "heavy" lifting of parsing out numbers accordingly, but I understand that there are any number of reasons you might want to maintain a distinction.

Regarding operators on the whole, I think the language would do well to carry provisions like dup and retr to their logical conclusion, namely that any unambiguous substring should be considered a valid instruction. Vim does this well, but how liberally to apply the rule‒again, if at all‒might be worth deliberating. Also, =, >, <, and ! should be acceptable synonyms where relevant. :)

The new operator is curious. If you're quite certain that it should only ever be used to initialize arrays, might it not be better to rename it array? I've implemented new thoroughly just in case; I think being able to dynamically create things like hashes, sockets, and perhaps even images in StackStack would be pretty interesting.

Finally, a few words on functions, largely the syntax thereof. As it stands, they must be defined on a single line; this isn't particularly good for readability, and StackStack is certainly powerful enough that its functional capabilities needn't be relegated to throwaway "macros". I can't help but assume you share my aesthetic appreciation of the following:

$fib
  dup 1 > if
    dup  1 - @fib
    swap 2 - @fib
  + endif

This introduces the issue of how to go about delimiting them, but I'll leave that alone pending your thoughts on the matter as a whole. I'm also going to refrain from going into closures, lambdas and treating functions as values. :P

I do apologize if this is all rather overbearing for a project you undertook solely for the sake of entertainment. All of this functionality surely exists in one or more established stack-based languages, but there really is something to StackStack's simplicity (that I apparently mean to destroy) that I'm drawn to. Feel free to let me know that you're content with leaving the language as it is, but I look forward to hearing from you either way.

(Out of curiosity, how do you feel about .st2 as the de facto extension?) Deciode (talk) 10:32, 23 August 2013 (UTC)

Firstly, thanks for your interest in this project! My friend suggested putting up the esolangs page on Stackstack, but I didn't really expect too much interest in the language.
I did write Stackstack and its first interpreter as an entertainment project and see whether I was able to create a real language, and not ones of the way too many Brainfuck clones lying around. I don't, however, think your remarks are out of place as I don't (yet) consider it to be a language "ready for the world".
About that race -- the Brainfuck-to-Stackstack converter is already there, just look in the examples list. A real interpreter is going to be slightly more challenging looking at the [ and ] instructions.
The Unicode awareness is something I hadn't really thought about yet, but I think that it is not really necessary for every Stackstack implementation to have Unicode support. It would indeed be particularly easy to support in Javascript but there are plenty languages around that are not as blessed :) Besides, isn't a Stackstack interpreter in Javascript already Unicode-aware by default? You don't really have a choice :P
The alert operation was mainly added to the language as a way to deliver some output to the user immediately, seeing as that is pretty much impossible in Javascript except if you want to mess around with setInterval() and friends. I didn't do that because I thought it was too much hassle. I suppose it would be nice to support the same I/O behaviour as a C, C++, Python, or any console-ready language has, but Javascript doesn't support that. (Race you to the Stackstack interpreter in C++ :)) For a console-based interpreter, I suggest making inputnum and inputstr read from stdin and alert write to stderr, possibly colouredly in supporting terminals.
I understand your opinion about tostring, and yes I do see myself type dup tostring print all over the place. The original reason was to save those implementing Stackstack in C++ some code, but in retrospect that seems thoroughly unnecessary indeed :) I'll think about automating the process in the print function, thus retaining backward compatibility. As a side note, are you maybe drawn to expanding Stackstack bit by bit to fit Javascript? :P
About input, you have pretty much two choices in getting strings and numbers: inputnum and inputstr or input(str) and int, the latter converting a string to an integer. I chose the first option, but it may be that the second option gives a little more flexibility. When, however, would one not know in advance whether some input is going to be some string or a certain number? I haven't seen such a case yet.
I like your suggestion of supporting a substring of a command as a valid representation of said command, but I suppose you mean a substring from the beginning? I haven't really used Vim so I can't use that as a reference. It would indeed be a good idea, as well as commonly used symbols for various operations. The only thing is that I think programs will get much more unreadable with the short commands. Now this is esolangs.org, so it would be fun, but maybe not as a main feature of the language. I'm thinking about implementing it though, and of course you can :)
The new operator is largely a stub function, as you correctly assumed. You're suggesting some interesting datatypes, and I like the idea of having them, but for myself I'll leave that to the time when I feel ready to implement Stackstack in C++. So, not yet.
Now the moment you're talking about going from macros, as they indeed quite are, to functions, I think you're lifting this (maybe fun but still) little language a bit too high. Yes, the function syntax you describe is good, actually a little bit like Python (intendedly?), but it clashes somewhat with Stackstack's feature that all terms may be separated by any amount of whitespace. Therefore I'd rather choose something like deffun and endfun (excuse the pun in the latter name). Is this clear though?
"fib" deffun
  dup 1 > if
    dup  1 - @fib
    swap 2 - @fib
  + endif
endfun
Ah well, maybe it is :) In this case deffun and endfun are not really operators like the others though. Maybe something like this then:
$fib{
  dup 1 > if
    dup  1 - @fib
    swap 2 - @fib
  + endif
}
… with the $funcname{ without spaces, obligatory, and the } separated from surrounding terms by whitespace, obligatory. Actually, I think this last version may be a good idea!
Just for my curiosity, what nationality do you have and how old are you? I'm Dutch and 15 years old :)
… And yes I do like the .st2 extension :D T.J.S.1 (talk) 17:10, 23 August 2013 (UTC)
Sure thing! Sorry for taking so long to get back to you, but I assure you, the interest is just as much my own pleasure. Thank your friend from me for convincing you to unleash StackStack unto the esolang community. I had my suspicions that you'd designed the language both as a hobbyist and as somebody bored with the deluge of languages just barely classifiable as "esoteric". I admit to not having pored over the semantics of all‒at the time of this writing‒799 non-joke languages here, but something just feels right about number eight hundred. (What a coincidence, huh?)
Really, though, combining the elegance of stack manipulation with reasonable flow control and the ability to define functions makes for a wonderful programming experience. I hinted earlier at having tried my hand at Forth. While it has all of the same building blocks as StackStack (and more, of course, but all in due time), its "busy" syntax just makes everything less pleasant. It's entirely possible that we might end up bloating the language, but I suspect we'll realize when we've gone too far. :) Now, then, back to business.
Yes, I certainly did take notice of your "bf2.st2" translator‒glad you like the extension, by the way. In fact, it was that program which revealed a rather large bug in my while implementation, so thank you for that as well. In my experience, (nested) looping is usually the trickiest hurdle to fully interpreting brainfuck, but memoizing the jump indices tends to make everything much easier. In fact, I even use this technique in my StackStack interpreter, which I'll be getting to in a moment.
You're quite right that supporting Unicode‒hell, even just non-ASCII‒can be a hassle in some languages, so it makes sense to not enforce it as part of the specification. I freely confess that Ruby has spoiled me in this regard. As for inherent Unicode-awareness, I meant to imply that it could be "hidden", so to speak. What, for instance, should "オ" ascii leave in its place? If 12458, then that operator is sorely misnamed, and if 42, the host language's Unicode support is immaterial if it's going to be circumvented. You do have a choice, and you must choose. :P
I was going to mention that you wouldn't even be able to store certain strings in your (presumably) native language, but apparently Dutch is completely covered by the basic Latin alphabet. That totally ruined the most persuasive part of my defense for Unicode support, but then I discovered that you chose well. How do you feel about renaming ascii to code(point) and having ascii return the mod-128 value instead? Also, now seems as appropriate a time as any to answer your question a little ahead of schedule: I'm Singaporean by birth, but I've spent the better part of my twenty-one years here in the States.
Yes, grinding things to a halt is pretty much the alert() procedure's signature move, and I can imagine why you might have needed it at one point or another; I used stop more than I care to admit when I was tinkering with more complex branching situations, and I'm sure I'll have to use it again. I did play around with your suggestion of alerting color to stderr, but it just doesn't have the same effect; I hope this won't offend, but the operation seems largely vestigial outside of JavaScript, and I think I'll refrain from implementing it.
On the bright side, I hope you'll be pleased to learn that JavaScript can and very much does exist outside of the browser: there are quite a few JS shells. As evinced by its position in Mozilla's list, Node is pretty much the standard. That so many of the libraries are "evented" and situated around callbacks might be annoying at first, but it could certainly be used to implement a full-fledged console version of StackStack in your abysmal wonderful language of preference. ;)
It's all a matter of balance, I suppose. It's unfortunate that JavaScript in the browser can't reliably read input without a graphical "intrusion", but at least it natively can do so when the situation calls for it. As for output, most modern consoles provide a subset of these features, but the one I linked directly is far and away the most powerful. Even then, it's nothing you couldn't already do on the page itself. I suspect that StackStack is going to become a much more interactive language with time, in which case JavaScript might well end up being the only sane language with which to interpret it.
On sanity, I genuinely considered attempting to write my interpreter in C. All the amenities Ruby provides make it seem like I'm hardly writing the program, and I yearn for the sound of smashed stacks as I attempt to refrain from setting any arbitrary limits on the sizes of my dynamic variables, but then I remember just how truly pleasant it can be and often is to write Ruby code and the hankerings for the ascetic bliss of C subside for a while.
As you demonstrated with your sum example, tostring is serviceable. Still, it makes just as much sense to automatically cast concat's arguments as well, especially since join already does so. "Be liberal with what you accept" advises backward compatibility, but now might be the ideal time to break it before our implementations diverge too considerably. That said, I've hitherto tested all of my programs‒sans the fancy stuff‒against both interpreters, and would certainly prefer to maintain parity between the two for as long as is feasible.
I cannot wait to begin collaborating on new bits to add to the language, but I doubt I'll be doing so specifically with JavaScript in mind. While my strikeout above was predominantly jest, it's become borderline disheartening for me to code for leisure in anything that isn't Ruby nowadays. (I'm going to stop proselytizing on your talk page now.) While our approaches to interpreting StackStack are remarkably different, I'd be happy to provide any insights I might have when it comes to implementing new features on your end.
I'm having trouble deciding whether I want to incorporate argument guards as stringently as you've done. It's just that it feels very strange to deliberately remove sensible, native behavior provided by the host. For instance, both our languages allow for lexicographical comparison of strings with < and >; should we really be eschewing freebies like that? Also, I can't think of any good reason for restricting storage keys to string values, but mayhap I've missed an informed decision there. Well, now that my dirty little secret is out, here's my interpreter. If and when I figure out this type-checking impasse, I'd like to give it a Web presence as well; putting it in front of a browser would greatly facilitate any "visual" features we might hit upon.
That thing I said about input was dumb; of course one might occasionally want to receive a string of digits. Please attempt to forget my mental lapse there.
Alas, the word "substring" has had its meaning convoluted. People often use it when they instead mean "subsequence" or, as you hinted at, "prefix". Pedantry aside, I see no reason to exclude any of them on principle; dup, cat, and slen are all perfectly intuitive, the last perhaps only just. I do enjoy brevity in code (would that I did so in discourse, eh?), but only up to a responsible limit. If we took a page out of Vim's book and gave preferential disambiguation to the commoner operations, we might end up with something like this (Haskell for comparison):
$f d 1 > if d 1 - @f s 2 - @f + fi
f = 0 : 1 : zipWith (+) f (tail f)
It's disgusting, but I can't look away. Well, let me know to what degree you decide to permit substrings and I'll adjust my approach accordingly. As for new, it certainly has the potential to become the most complex and interesting operator. Outside of using hashes to play around with function-local variable stores (closures, essentially), I'm not too sure what else I'd do with it for now, so I don't particularly mind leaving it alone for the time being.
Are you saying that you accidentally included full support for multivariate recursion in a macro system? :P In all seriousness, I think StackStack is very close to being worthy of consideration as "functional". For starters, the integrity of the syntactic freedom need only be compromised in a single place; so long as two consecutive newlines signify the end of a function definition, there is no ambiguity and no impact on other code:
-2 # Just making sure functions don't need to be at the top.

$fib
  dup 1 > if
    dup  1 - @fib
    swap 2 - @fib
  + endif

$fac dup 2 > if
       dup 1 - @fac *
     endif

6 @fib 4 @fac
5 @fac 9 @fib

1800 + + + + + print
It does bear a thin resemblance to Python, as well as many other off-side rule languages, but not intentionally; that's just how code tends to look when it's aligned "logically", for some definition of the term. Besides, StackStack one-ups those languages in several ways: there are no obligatory (nor optional :P) delimiters, no syntactically illegal whitespace, and the rule itself subtly forces us to write more legible, organized code. For instance, consider how we might go about dividing up portions of a function body without prematurely breaking out of its definition:
$Ack
  swap dup if
    swap dup if
      1 - swap dup
      # m > 0, n > 0
      1 - -3 roll swap @Ack @Ack
    # m > 0, n = 0
    else pop 1 - 1 @Ack endif
  # m = 0
  else pop 1 + endif

4 2 @Ack print
If we could find the stack space, this program would eventually print all 19,729 digits of 265536 - 3. Sure, we could do without the comments in this case, but it demonstrates the technique. Wherever we might want to separate the logic of a function, the rule whispers that perhaps we should explain why. The elegance is almost uncanny. In cases where the intent is simply to offset some setup, an empty comment might suffice:
$prn 10 char cat print

$log_eso
  "irc.freenode.net" 6667 "tcpsocket" new
  swap "PASS " swap cat @prn
  swap "USER " swap cat @prn
  "JOIN #esoteric" @prn
#
  read while
    swap @prn swap
  read endwhile
  
"eso.log" "file" new
"stackbasedgod" "hunter2" @log_eso
Remember to parse comments up to and including their newlines, though, otherwise the rule is bound to be invoked unexpectedly. I haven't slept in what feels like ages, and perhaps I'm not thinking quite straight, but the two newlines thing seems to solve every relevant problem without introducing any of its own. Please inform me if you come to possess any sentiments to the contrary.
I'm totally blind to the appeal of using special keywords or obligatory braces to delimit function code, so I'm hoping you're not too attached to those suggestions. Certainly, they would fit in many other languages, but they somehow feel "off" for this one, and we must protect #800's purity. That said, I have a few ideas that would introduce a bit of complexity into the language as the price for a marked increase in expressiveness, but I shall save those for another chapter. ^_^
I have three curiosities this time: which distro/editor do you use and why won't you capitalize the second S? :D Deciode (talk) 18:20, 24 August 2013 (UTC)
Wow, how did you notice StackStack was non-joke language number 800 precisely? I didn't, anyway. Maybe a sign that it's destined to become a nice language? :P
I hadn't looked into Forth yet, so I took a quick peek at its Wikipedia page, and indeed it bears an uncanny resemblance to Stackstack! Even some operators are the same, but I guess they come naturally… :) (dup, if, else, etc.) Ruby is also pretty new for me so trying to read your interpreter was somewhat hard. I did notice that your looping implementation is about as different from mine as can be. You seem to precompute every branch (for whatever that means in your program, the i, @I, w, ws till end block is pretty much unreadable for me, though I suppose you're memorising the jump targets of all matching while's and if's), while I do the looping and looking for matching (end)while's etc. on demand. I suppose the reason why I took this approach is that my background is really C and as such my programming style is as imperative as C is.
Interesting question about the Japanese character. Yes, indeed, my native language completely fits within the basic ASCII character set, unlike oh so many others, but I do agree about ascii and its misnaming. Therefore, yes, I choose: we will have a Unicode-ready version of ascii. Non-supporting implementations may see them as synonyms. I'm unsure however about the naming of the Unicode-ready function however. Should we take the "modern" codepoint or the classical ord? I tend towards the latter because of its inherent shortness (how would you efficiently abbreviate "codepoint"?) and the fact that it's pretty well known. About your nationality: I could probably have guessed given your master of English :)
YAY I'm not the only one liking the Ruby/Javascript rant! :D The good thing is that Bernhardt apparently thinks Ruby sucks too (though I do frown on JS's [] + {} vs {} + [] lol). I know about Node.js but haven't used it much yet. And I sincerely do not like "evented" systems! (The Windows API is one of the things I'm aiming at right now… The WinAPI is bad in general by the way.) There's one thing you do have to admit about JS: there isn't a language that hasn't as many dark corners. Consider, for example, this snippet:
function one(){
    return true;
}
function two(){
    return
        true;
}
console.log(one());
console.log(two());
I don't know whether you've already seen this example of gruesomeness, but the first log statement logs "true" and the second logs "undefined". Why? Because of automatic semicolon insertion. In two(), the JS interpreter recognises a statement (return) without a terminating semicolon (which is allowed BTW), and adds the semicolon, resulting in:
function two(){
    return;
        true;
}
This, obviously, returns undefined as there's no argument to return. Now whatever language you choose to compare to, this behaviour is unique (and bizarre) as far as I know.
As to your remark about StackStack getting too interactive for any language besides Javascript — I'd regret it if that happens. As much as I like JS (save said bizarrities), I think other languages have just as much right for existence. I'll take your silent suggestion, though, and attempt to write a C++ interpreter when I get the motivation to. I'll have to deal with casting, but I see the beneficial value of automatic casting like what happens nowadays in most high-level languages. (For some reason, Python is out though, because "one "+2+" three" errors on a missing call to str().) And what are you aiming at when mentioning non-string variable key names? I'd rather have 1 "var" store store it in "1" than in 1, which would happen automatically already with the proposed liberal type system.
I don't really like arbitrary substrings (as in, any sequence of characters that uniquely identifies a command, like lat uniquely identifies duplicate); that should be reserved to the editor, like Sublime Text 2 does. I like to stay with prefixes (like al for alert and as for ascii). Your Haskell example illustrates my main motivation: that, although brief, code shouldn't be unreadable, except when [codegolf.stackexchange.com code golfing].
In fact, as you might have guessed, I know very little about fucntional programming, so I don't really know what you're talking about with "multivariate recursion". I do see that the system is reasonably powerful, and I think that your suggestion of ending a function with two consecutive newlines is nice. Here's something that made me think: what if there's more whitespace on the "empty" line than just a newline? What if people use some editor that automatically continues indentation and keeps it until manually removed? Will that break the function ending? I think that that would be an error that's extremely hard to spot, as "empty" lines look empty. (Don't they? lol) By the way, I just tested it in Sublime Text 2 and the problem doesn't exist there. If you press enter twice, you still have indentation, but pressing backspace then removes both. Yay for ST2!
Now the empty comment is nice and all, but the whispering continues: the lonely hashtag whispers that maybe he can be unnecessary. It looks like a workaround for some problem, anyway, while there is no problem. And yes, even without your lack of sleep, that's the only thing I can come up with as non-beneficial about the double LF rule. :D By the way, no the suggestion for function delimiters as separate terms was just another possibility, not a decision at all. You can rest in peace. ;)
Now for your three curiosities: I'm not on Linux, so the word "distro" may be out of place, but I'm mostly using Mac OS X (10.8) (which I love because of its nice interface while having a window open to Unix in the terminal) and a laptop running Windows 7. I use the latter for stuff that doesn't work/run on Mac and for school work as I don't have MS Office on Mac. :P By far my favourite editor around is Sublime Text (as you might've guessed), and I usually don't capitalise the second S because I'm lazy. >:D
T.J.S.1 (talk) 06:48, 25 August 2013 (UTC)
Well, I was going to use whatever number grep gave me; it ended up being 799, and I was pleased to discover that StackStack wasn't yet in the list. It's already a nice language, but that it's also a "century" language on this wiki is certainly amusing.
"Forth-like" is definitely the most succinct description of StackStack, but I'm confident we can improve on the design. I was pretty sure you'd mention that monster of a code block, but hopefully my explanation of its mechanism can salvage your opinion of me. :P
For starters, here is a much more legible rendition. It still uses a few Ruby idioms, but hopefully it clarifies the technique a bit. As an example, if "yes" else "no" endif would be represented as {0: 2, 2: 4}, whereas 10 dup while 1 - dup endwhile would be {2: 6, 6: 2}. "Branching" isn't my word, by the way; it refers to any time the execution of a program might go one way or another, such as during while loops and as the result of if statements. Calculating the branches only as often as necessary (once, essentially) is a great way to improve performance, and I would strongly recommend familiarizing yourself with the general principle for potential future use.
Along a similar vein, I noticed that you splice function bodies directly into the main program during execution. It works, certainly, but at the end of 3 4 @Ack, the size of the code string has ballooned to over a megabyte. Sure, the Ackermann function is something of a pathological case, but I do think it helps send home the point. This feeds back into the bit about branching; imagine how much needless iteration and backtracking gets performed when a recursive function finds itself being called inside a while loop. All this said, your interpreter runs reasonably quickly, and I apologize if you take offense with my pedagogy. I understand that it might be difficult to incorporate these improvements, but I do think it'd be worthwhile, even if only as a learning experience.
I agree entirely with your encoding choices, and our ascii and ord operations behave identically. Thank you for the compliment, of course. Outside of‒accidentally, I should hope‒telling me to "rest in peace", your English is quite good given your youth. :P
I'm glad Bernhardt also poked fun at Ruby, or else I might have just come across as mean. That said, a = a's behavior almost makes sense, and method_missing really is both beautiful and terrifying. JavaScript certainly has its warts, but few if any of them are insurmountable. I shall refrain from speaking the name of the language I think has the darkest corners.
I mostly suggested a pursuit of interactivity given the JavaScript foundations in place, but I understand not wanting to limit adoption. As for Python not adding numbers and strings, it's easy enough to pass everything through the str() function for the concat operation. As for non-string keys, that was the Ruby speaking again. It's rare, but I've encountered situations where it made sense to use arrays as keys. I realize that JavaScript doesn't make this anywhere near as easy (and also that it doesn't differentiate between string keys and numeric ones in the first place), so disregard that suggestion.
I confess that potential golfing was something I had in mind, but it certainly isn't worth overhauling the language for. Prefixes generally make much more sense (though I do quite like cat), it's just a matter of ensuring our interpreters agree.
I may have put more fancy a spin on it than was called for. I was referring to the fact that StackStack can define the Ackermann function, which can end up calling itself twice. I suppose that's largely a byproduct of being stack-based, but it still speaks to the overall power of the system. I have Vim set up to kill trailing whitespace on save, but it's good that ST2 doesn't make it too hard to remove. Unintentionally empty lines would certainly cause problems, but it's easy enough to consider "blank" a line that matches /^\s*$/.
The lonely hashtag is unfortunate, though. I suppose the options are either not commenting, commenting frequently, or finding some less aesthetic means of delimiting functions. It's a little odd, but we could instead use some form of tag at the end of a line that signifies that the upcoming blank line shouldn't end the function. It'd still look "off", but perhaps not as much as the current proposal.
I noticed you added the floor command, and I caught a flash of insight. Given that floor can readily be implemented in StackStack itself with ~ ~, I considered whether it'd make sense to allow functions to be called without the @ sigil. That is, when a term hasn't yet matched, one last attempt is made to see if it refers to a previously defined function before throwing unrecognized. I've added this functionality to my interpreter, and I think it'd be fairly easy to augment the default branch of your main switch statement. Now, permitting this syntax for the sake of floor wouldn't be very interesting. Consider this, though:
$[ size "s" store

$]
  "array" new
  size "s" retr -
  1 - dup while
    dup 2 + roll
    3 roll swap push swap
  1 - dup endwhile pop

[ 1 2 3 4 ] sum
Array literals, implemented entirely in StackStack! I think it's pretty awesome, but perhaps you'll have your reasons for wanting to keep the sigil. Either way, the language is definitely quite capable, but I think it's time we added a few more useful operations. Given how conveniently we can create them now, I think arrays could use a few more features; reverse, uniq, and index come to mind. Deciode (talk) 22:51, 28 August 2013 (UTC)
Thanks for the "readable version" of the branch mapping code block — I get what you're doing there now. I knew of the concept of branching but I hadn't really considered optimising the interpreter in this way. I like it, though. :)
I'm working on the project of translating my JS interpreter to C++ (which is quite a job!), and in fact the first error-free compilation is somewhat in sight I skipped implementing array's because of my non-extendable way of storing items on the stack. (Yay for JS and its type-ignorance — you can literally throw anything you want in any variable. Try doing that in C++.) I'm going to transform it into something more extendable though, since indeed the new operator has the potential to do pretty interesting things, as you noted.
I think I might even use your technique in my C++ interpreter, precomputing all the branching and making the implementation more modular so we can execute functions recursively. Let's first finish it though :)
Wow — sorry for that mistake. Indeed I didn't mean to say that! I'm still learning! :) In fact I'm doing a bilingual program at high school, which means, roughly spoken, that (along with the rest of my class counting about 25 people) I'm getting lots and lots more English than the rest of the school. I've got my Cambridge CAE and we're working towards an IB certificate in sixth grade, but I'll first have to work through fifth grade :) By the way, school is starting again for me next week so I won't have a lot of time to work on programming.
Using arrays as variable names may in a weird scenario make sense but I don't think a "normal" (is StackStack normal? :P) language has to support them. I wouldn't know how to use them either :)
About the prefixes and cat: I think cat just has to become an alias. We'll create the equal command to let eq be a shortening of that; to me that sounds good. It would probably be nicest to only accept shortenings uniquely defining a certain command, but is it acceptable that terms that are too short for that, e.g. sto, produce undefined behaviour in that they can map to any of the matching commands? (In practice they will then map to the first match when sorted alphabetically.) An implementation like that will be slightly easier since it won't have to continuously check whether the term is unique. Tiny speedups ;)
I support your definition of a blank line as one matching /^\s*$/.
:)
In short, we have two choices about function definition delimiting: (1) we could have a blank line delimit a function, having some character that signifies continuation of the function, or (2) we could have another function delimiter, so, other than a blank line. I really like the forced neatness of (1), but I don't think something like the following looks really bad:
$fac
    dup 2 > if
        dup 1 - @fac *
    endif
$!
In that example, $! is the function delimiter. Maybe it's too small or inelegant, I don't know. What's your opinion? This format would actually allow you to write 5 functions in 5 lines (and if you really want to, 5 functions on 1 line even!), which I think is good. It also allows you to write code with blank lines right in the middle of a function without breaking the syntax.
Now about a floor implementation: in Javascript (so also in StackStack, in this case) one can floor a value with either Math.floor(value) or ~~(value), in the latter the parentheses being unneeded if value is a single value, variable or function (~ sits pretty high in the order-of-operations-list). Watch out though, because there is a small but significant difference between the two methods. Look at this example, output in comments: (Javascript)
console.log(~~2.5); //2
console.log(Math.floor(2.5)); //2
console.log(~~-2.5); //-2 (!)
console.log(Math.floor(-2.5)); //-3 (!)
The exact same behaviour can be seen in C (or C++):
#include <stdio.h>
#include <math.h>

int main(void){
    printf("%d\n",(int)2.5); //2
    printf("%d\n",(int)floor(2.5)); //2
    printf("%d\n",(int)-2.5); //-2 (!)
    printf("%d\n",(int)floor(-2.5)); //-3 (!)
    return 0;
}
This is why I added floor. It can be implemented in StackStack the right way (like floor()) like this:
$floor dup 1 % abs -
I think a built-in floor is easier in this case. This, by the way, also makes use of my just-added function abs, which StackStack was still missing for some reason.
Fun fact: I guessed the meaning of the word sigil from the context since I didn't know what it meant, but I decided to look it up. Wikipedia says it's magic. :P
Have you ever played with Logo? It enforces sigils in a similar way to what StackStack's doing now, but then for variables. Functions can be called just like built-in ones, but variable references have to have a colon. Example: (Logo code, equivalent C++ in comments)
make "varA 42  ; int varA=42;
make "varB 13  ; int varB=13;
make "varC :varA+:varB  ; int varC=varA+varB;
print :varC  ; cout<<varC<<endl;
And yes, the semicolon is the only comment character in Logo. Now for a weird-ass language. Anyway, that's partly where $ and @ come form in StackStack. I do see the use in removing that prefix (your array code is pretty awesome! :D), but I like the way it unambiguously distinguishes a built-in function and a user-defined function, so I think I'll keep it. I feel it gives kind of a more "special" feeling, though indeed that's pretty personal. :)
Thanks for the suggestions for array functions. Using our prefix idea, I'll call them reverse, unique and indexof, since your Ruby variants are prefixes of those and I think the latter two are a bit clearer.
Again, response times may increase a little since school is starting in a few days, but I'm excited we're improving the language! :D
T.J.S.1 (talk) 09:28, 31 August 2013 (UTC)